diff --git a/docs/contest_runners.md b/docs/contest_runners.md index 8db6ddf..b19b158 100644 --- a/docs/contest_runners.md +++ b/docs/contest_runners.md @@ -12,13 +12,32 @@ TORCH_THREADS=48 \ SEARCH_REPEATS=2048 \ SEARCH_TIME=300 \ SCHEDULER_HOST=10.20.1.103 \ -WORKER_HOSTS="10.20.1.103 10.20.6.101" \ +WORKER_HOSTS="10.20.1.103 10.20.1.101" \ DASK_ADDRESS="tcp://10.20.1.103:8786" \ NWORKERS=84 \ NTHREADS=1 \ MPIEXEC_FULL="mpirun -np 4 -hostfile /home/yx/qibotn/hostfile -perhost 2" \ tools/run_tn_dask_mpi_all.sh + + +I_MPI_FABRICS=shm:ofi \ +I_MPI_OFI_PROVIDER=tcp \ +FI_PROVIDER=tcp \ +CASE=main1 \ +OBSERVABLES=long_z_string \ +NQUBITS=34 \ +NLAYERS=20 \ +TORCH_THREADS=48 \ +SEARCH_REPEATS=2048 \ +SEARCH_TIME=300 \ +SCHEDULER_HOST=127.0.0.1 \ +WORKER_HOSTS="127.0.0.1" \ +DASK_ADDRESS="tcp://127.0.0.1:8786" \ +NWORKERS=12 \ +NTHREADS=1 \ +MPIEXEC_FULL="mpirun -np 2 -hostfile /home/yx/qibotn/hostfile -perhost 2" \ +tools/run_tn_dask_mpi_all.sh # 单独缩并contract计算 I_MPI_FABRICS=shm:ofi \ @@ -43,11 +62,16 @@ cd /home/yx/qibotn I_MPI_FABRICS=shm:ofi \ I_MPI_OFI_PROVIDER=tcp \ FI_PROVIDER=tcp \ -MPIEXEC_FULL="mpirun -np 4 -hostfile /home/yx/qibotn/hostfile -perhost 2" \ +MPIEXEC_FULL="mpirun -np 2 -hostfile /home/yx/qibotn/hostfile -perhost 2" \ TORCH_THREADS=48 \ OBS_FILTER=ring_xz \ MAIN1_NQ=128 \ MAIN1_LAYERS=24 \ -MAIN1_BOND=1024 \ +MAIN1_BOND=512 \ tools/run_vidal_mpi_contest_cases.sh main1 -``` \ No newline at end of file +``` + + + 136.997 + + \ No newline at end of file diff --git a/hostfile b/hostfile index 19358eb..794bc16 100644 --- a/hostfile +++ b/hostfile @@ -1,2 +1,2 @@ 10.20.1.103:2 -10.20.6.101:2 +10.20.1.101:2 \ No newline at end of file diff --git a/src/qibotn/backends/qmatchatea.py b/src/qibotn/backends/qmatchatea.py index 41381dc..6dde758 100644 --- a/src/qibotn/backends/qmatchatea.py +++ b/src/qibotn/backends/qmatchatea.py @@ -12,6 +12,7 @@ from qibo.config import raise_error from qmatchatea.utils import MPISettings from qibotn.backends.abstract import QibotnBackend +from qibotn.circuit_fusion import fuse_qiskit_one_qubit_gates from qibotn.observables import check_observable from qibotn.result import TensorNetworkResult @@ -287,6 +288,7 @@ class QMatchaTeaBackend(QibotnBackend, NumpyBackend): if not preprocess: if compile_circuit: qiskit_circuit = qmatchatea.tensor_compiler(qiskit_circuit) + qiskit_circuit = fuse_qiskit_one_qubit_gates(qiskit_circuit) return qiskit_circuit # Transpile the circuit to adapt it to the linear structure of the MPS, @@ -297,6 +299,7 @@ class QMatchaTeaBackend(QibotnBackend, NumpyBackend): tensor_compiler=compile_circuit ), ) + qiskit_circuit = fuse_qiskit_one_qubit_gates(qiskit_circuit) return qiskit_circuit def _qiboobs_to_qmatchaobs(self, hamiltonian, observable_name="custom_hamiltonian"): diff --git a/src/qibotn/backends/vidal_mpi_segment.py b/src/qibotn/backends/vidal_mpi_segment.py index 1014588..671dc8a 100644 --- a/src/qibotn/backends/vidal_mpi_segment.py +++ b/src/qibotn/backends/vidal_mpi_segment.py @@ -124,7 +124,7 @@ class SegmentVidalMPIExecutor: gates = circuit.queue if compile_circuit: gates = _route_non_adjacent_gates(gates, circuit.nqubits) - gates = _fuse_one_site_blocks(gates) + gates = _fuse_one_site_blocks(gates) for batch in _disjoint_batches(gates): if _is_two_qubit_batch(batch): self._apply_two_site_batch(batch, timings) diff --git a/src/qibotn/backends/vidal_tebd.py b/src/qibotn/backends/vidal_tebd.py index 25f001e..fb8c921 100644 --- a/src/qibotn/backends/vidal_tebd.py +++ b/src/qibotn/backends/vidal_tebd.py @@ -194,7 +194,7 @@ class VidalTEBDExecutor: gates = circuit.queue if compile_circuit: gates = _route_non_adjacent_gates(gates, circuit.nqubits) - gates = _fuse_one_site_blocks(gates) + gates = _fuse_one_site_blocks(gates) for batch in _disjoint_batches(gates): for gate in batch: self._apply_gate(gate) diff --git a/src/qibotn/circuit_fusion.py b/src/qibotn/circuit_fusion.py new file mode 100644 index 0000000..14c895a --- /dev/null +++ b/src/qibotn/circuit_fusion.py @@ -0,0 +1,68 @@ +"""Circuit-level gate fusion helpers.""" + +from __future__ import annotations + +import numpy as np + + +def fuse_qiskit_one_qubit_gates(circuit): + """Fuse consecutive unconditional one-qubit gates in a Qiskit circuit. + + The fused gate is emitted as a Qiskit ``UnitaryGate``. qmatchatea's Qiskit + executor applies generic gates through ``operation.to_matrix()``, so this + reduces Python gate dispatch without changing the physical circuit. + """ + + from qiskit import QuantumCircuit + from qiskit.circuit.library import UnitaryGate + + fused = QuantumCircuit(*circuit.qregs, *circuit.cregs, name=circuit.name) + pending = {} + + def qubit_index(qubit): + return circuit.find_bit(qubit).index + + def flush_qubit(index): + matrix = pending.pop(index, None) + if matrix is not None: + fused.append(UnitaryGate(matrix, label="fused1q"), [fused.qubits[index]]) + + def flush_all(): + for index in sorted(tuple(pending)): + flush_qubit(index) + + for instruction in circuit.data: + operation = instruction.operation + qubits = instruction.qubits + clbits = instruction.clbits + condition = getattr(operation, "condition", None) + + can_fuse = ( + len(qubits) == 1 + and len(clbits) == 0 + and condition is None + and hasattr(operation, "to_matrix") + ) + if can_fuse: + try: + matrix = np.asarray(operation.to_matrix(), dtype=np.complex128) + except Exception: + can_fuse = False + + if can_fuse: + index = qubit_index(qubits[0]) + if index in pending: + pending[index] = matrix @ pending[index] + else: + pending[index] = matrix + continue + + touched = {qubit_index(qubit) for qubit in qubits} + for index in sorted(touched): + flush_qubit(index) + if len(qubits) != 1: + flush_all() + fused.append(operation, [fused.qubits[qubit_index(q)] for q in qubits], clbits) + + flush_all() + return fused diff --git a/tools/tn_contest_runner.py b/tools/tn_contest_runner.py index 40de960..bd1a8f8 100644 --- a/tools/tn_contest_runner.py +++ b/tools/tn_contest_runner.py @@ -47,7 +47,7 @@ CASES = { "main1": CaseSpec( circuit_kind="rxx_rzz_chain", observables=("ring_xz",), - nqubits=34, + nqubits=37, nlayers=20, seed=31001, target_slices=None, diff --git a/trees/contest_tn/main1_long_z_string_34q20l_auto.pkl b/trees/contest_tn/main1_long_z_string_34q20l_auto.pkl index 55ac205..31ef070 100644 Binary files a/trees/contest_tn/main1_long_z_string_34q20l_auto.pkl and b/trees/contest_tn/main1_long_z_string_34q20l_auto.pkl differ