From 4bfb683d0041169ff30ef7d8b5834a5bc519497f Mon Sep 17 00:00:00 2001 From: Matthew Treinish Date: Fri, 11 Dec 2020 14:22:46 -0500 Subject: [PATCH] Fix performance regression in CSPLayout pass In #5183 the inner graph object of the CouplingMap object was switched to retworkx. While generally faster there are a few different edge cases where retworkx performance can be worse than networkx. Namely, any place where large lists are returned, for example lists of all nodes or edges in a graph. In those cases the conversion from the Rust objects to the Python objects can culmulatively be expensive. To avoid this conversion overhead in every case retworkx has custom return types that are python sequences but defer type conversion to __getitem__, meaning that the return is fast but complete traversal can be slow, epsecially when done multiple times. In such cases it's easier to cast the sequence to a Python object such as a set or a list so the conversion is only done once. However, in the CSPLayout pass the edges list returned from retworkx was searched multiple times as part of the constraint function which resulted in a large performance regression. This commit fixes this by casting the local edges to a set(). This has 2 advantages, first it avoids the multiple traversals of the graph which removes the conversion overhead. The second advantage is that by using a set the lookups are constant time instead of iterating over the full list every time. This results in a performance improvement over the performance prior to #5183 and the introduction of the regression. --- qiskit/transpiler/passes/layout/csp_layout.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qiskit/transpiler/passes/layout/csp_layout.py b/qiskit/transpiler/passes/layout/csp_layout.py index 964356696240..ad35c38ccd44 100644 --- a/qiskit/transpiler/passes/layout/csp_layout.py +++ b/qiskit/transpiler/passes/layout/csp_layout.py @@ -106,7 +106,7 @@ def run(self, dag): for gate in dag.two_qubit_ops(): cxs.add((qubits.index(gate.qargs[0]), qubits.index(gate.qargs[1]))) - edges = self.coupling_map.get_edges() + edges = set(self.coupling_map.get_edges()) if self.time_limit is None and self.call_limit is None: solver = RecursiveBacktrackingSolver()