Skip to content

Commit

Permalink
Use numpy sum instead of comprehension in _score_heuristic (#5403)
Browse files Browse the repository at this point in the history
* Use numpy sum instead of comprehension in _score_heuristic

In sabre_swap the comprehension in _score_heuristic() with the basic
heuristic starts to become a bottleneck as the size of the coupling map
increases. This probably becomes the top bottleneck in a transpilation
after #5316, #5183, #5294, #5267, and #5272 are merged. This commit is
an attempt to try and mitigate that a bit by using numpy native
operations instead of a python comprehension in sum(). If this is
insufficient we'll likely have to either avoid doing a sum like this or
drop down to a lower level with cython or rust and operate on the array
directly to remove this bottleneck.

* Make distance matrix a coupling map property

* Fix tests

* Fix lint

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
  • Loading branch information
mtreinish and mergify[bot] authored Nov 25, 2020
1 parent a234c27 commit 2a40c62
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 2 deletions.
7 changes: 7 additions & 0 deletions qiskit/transpiler/coupling.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,13 @@ def neighbors(self, physical_qubit):
"""
return self.graph.neighbors(physical_qubit)

@property
def distance_matrix(self):
"""Return the distance matrix for the coupling map."""
if self._dist_matrix is None:
self._compute_distance_matrix()
return self._dist_matrix

def _compute_distance_matrix(self):
"""Compute the full distance matrix on pairs of nodes.
Expand Down
11 changes: 9 additions & 2 deletions qiskit/transpiler/passes/routing/sabre_swap.py
Original file line number Diff line number Diff line change
Expand Up @@ -314,8 +314,15 @@ def _score_heuristic(self, heuristic, front_layer, extended_set, layout, swap_qu
the remaining virtual gates that must be applied.
"""
if heuristic == 'basic':
return sum(self.coupling_map.distance(*[layout[q] for q in node.qargs])
for node in front_layer)
if len(front_layer) > 1:
return self.coupling_map.distance_matrix[
tuple(zip(*[[
layout[q] for q in node.qargs] for node in front_layer]))].sum()
elif len(front_layer) == 1:
return self.coupling_map.distance(
*[layout[q] for q in list(front_layer)[0].qargs])
else:
return 0

elif heuristic == 'lookahead':
first_cost = self._score_heuristic('basic', front_layer, [], layout)
Expand Down

0 comments on commit 2a40c62

Please sign in to comment.