From 0230ba57b7d4c31eb83bb8f3cc5afa660a51dbb7 Mon Sep 17 00:00:00 2001 From: Matthew Treinish Date: Wed, 4 May 2022 10:09:48 -0400 Subject: [PATCH 1/3] Remove hard time limit from vf2 passes in preset passmanagers This commit removes the hard time limit from the preset passmanager. We were previously setting two limits on the pass a call_limit parameter, which is used to set the limit of internal state visits the vf2 implementation in retworkx will attempt before giving up, and a time limit which sets a hard wall time limit that is checked after each mapping to ensure we don't spend more than a specific amount of time on trying to find an optimal mapping. As subgraph isomorphism is NP-complete we could spend a very large amount of time trying to find the next isomorphic mapping and both these limits were set to avoid a situation where we spend hours in optimization level 1 trying to find a better layout. However, as we've seen in #8017 setting a hard time limit limits the level of reproducibility on the output of the transpiler. It means that setting a fixed seed is no longer sufficient to exactly reproduce the output as it's also partially a function of the performance of the local system we're running on. If the local environment is slower we might get different results because we've hit the hard time limit. To address this, this commit removes the hard time limit so that we only rely on the call limit parameter on the preset pass manager. While this parameter is a bit more opaque in how it should be used because it requires an understanding of how the VF2 algorithm works (and is implemented in retworkx) it should be sufficient to avoid the runaway execution problem but also means the limits are determinitisically applied. This should improve the reproducability of the transpiler because the pass will always try exactly up until a given point regardless of how fast the local environment is. For people manually instatiating the pass they can still rely on the hard time limit parameter if they want it, but for the preset pass managers and the transpile() function we no longer set this. Fixes #8017 --- qiskit/transpiler/preset_passmanagers/level1.py | 2 -- qiskit/transpiler/preset_passmanagers/level2.py | 2 -- qiskit/transpiler/preset_passmanagers/level3.py | 2 -- 3 files changed, 6 deletions(-) diff --git a/qiskit/transpiler/preset_passmanagers/level1.py b/qiskit/transpiler/preset_passmanagers/level1.py index 76d1de8db6ea..efc29c660159 100644 --- a/qiskit/transpiler/preset_passmanagers/level1.py +++ b/qiskit/transpiler/preset_passmanagers/level1.py @@ -156,7 +156,6 @@ def _vf2_match_not_found(property_set): coupling_map, seed=seed_transpiler, call_limit=int(5e4), # Set call limit to ~100ms with retworkx 0.10.2 - time_limit=0.1, properties=backend_properties, target=target, ) @@ -325,7 +324,6 @@ def _post_layout_condition(property_set): backend_properties, seed_transpiler, call_limit=int(5e4), # Set call limit to ~100ms with retworkx 0.10.2 - time_limit=0.1, strict_direction=False, ), condition=_trivial_not_perfect, diff --git a/qiskit/transpiler/preset_passmanagers/level2.py b/qiskit/transpiler/preset_passmanagers/level2.py index 80ff4374e32b..65e54f4aefcf 100644 --- a/qiskit/transpiler/preset_passmanagers/level2.py +++ b/qiskit/transpiler/preset_passmanagers/level2.py @@ -154,7 +154,6 @@ def _vf2_match_not_found(property_set): coupling_map, seed=seed_transpiler, call_limit=int(5e6), # Set call limit to ~10 sec with retworkx 0.10.2 - time_limit=10.0, properties=backend_properties, target=target, ) @@ -312,7 +311,6 @@ def _post_layout_condition(property_set): backend_properties, seed_transpiler, call_limit=int(5e6), # Set call limit to ~10 sec with retworkx 0.10.2 - time_limit=10.0, strict_direction=False, ) ) diff --git a/qiskit/transpiler/preset_passmanagers/level3.py b/qiskit/transpiler/preset_passmanagers/level3.py index b896339cc7c0..e9b0337a5770 100644 --- a/qiskit/transpiler/preset_passmanagers/level3.py +++ b/qiskit/transpiler/preset_passmanagers/level3.py @@ -157,7 +157,6 @@ def _vf2_match_not_found(property_set): coupling_map, seed=seed_transpiler, call_limit=int(3e7), # Set call limit to ~60 sec with retworkx 0.10.2 - time_limit=60, properties=backend_properties, target=target, ) @@ -323,7 +322,6 @@ def _post_layout_condition(property_set): backend_properties, seed_transpiler, call_limit=int(3e7), # Set call limit to ~60 sec with retworkx 0.10.2 - time_limit=60, strict_direction=False, ) ) From 110379bb2b26c0f964774bb8aa13684049900f2a Mon Sep 17 00:00:00 2001 From: Matthew Treinish Date: Wed, 4 May 2022 12:01:37 -0400 Subject: [PATCH 2/3] Add release note --- ...-hard-time-limit-vf2-be83830ecc71f72c.yaml | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 qiskit/transpiler/preset_passmanagers/releasenotes/notes/remove-hard-time-limit-vf2-be83830ecc71f72c.yaml diff --git a/qiskit/transpiler/preset_passmanagers/releasenotes/notes/remove-hard-time-limit-vf2-be83830ecc71f72c.yaml b/qiskit/transpiler/preset_passmanagers/releasenotes/notes/remove-hard-time-limit-vf2-be83830ecc71f72c.yaml new file mode 100644 index 000000000000..88af99dfdb06 --- /dev/null +++ b/qiskit/transpiler/preset_passmanagers/releasenotes/notes/remove-hard-time-limit-vf2-be83830ecc71f72c.yaml @@ -0,0 +1,25 @@ +--- +upgrade: + - | + The preset pass managers generated by :func:`~.level_1_pass_manager`, + :func:`~.level_2_pass_manager`, and :func:`~.level_3_pass_manager` and used + by the :func:`~.transpile` function's ``optimization_level`` argument at + 1, 2, and 3 respectively no longer is setting a hard time limit on the + :class:`~.VF2Layout` transpiler pass. This means that the pass will no + longer stop trying to find a better alternative perfect layout up until a + fixed time limit (100ms for level 1, 10 sec for level 2, and 60 sec for + level 3) as doing this limited the reproducibility of compilation when a + perfect layout was available. This means that the output when using the pass + might be different than before, although in all cases it would only change + if a lower noise set of qubits can be found over the previous output. If + you wish to retain the previous behavior you can create a custom + :class:`~.PassManager` that sets the ``time_limit`` argument on the + constructor for the :class:`~VF2Layout` pass. +fixes: + - | + Fixed an issue with reproducibility of the :func:`~.transpile` function + when running with ``optimization_level`` 1, 2, and 3. Previously, under + some conditions when there were multiple perfect layouts (a layout that + doesn't require any SWAP gates) available the selected layout and output + circuit could vary regardless of whether the ``seed_transpiler`` argument + was set. From 15ed72480608bc7db60a463befb0a90854e1d65b Mon Sep 17 00:00:00 2001 From: Jake Lishman Date: Wed, 4 May 2022 17:05:47 +0100 Subject: [PATCH 3/3] Fix tense --- .../notes/remove-hard-time-limit-vf2-be83830ecc71f72c.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qiskit/transpiler/preset_passmanagers/releasenotes/notes/remove-hard-time-limit-vf2-be83830ecc71f72c.yaml b/qiskit/transpiler/preset_passmanagers/releasenotes/notes/remove-hard-time-limit-vf2-be83830ecc71f72c.yaml index 88af99dfdb06..4b73a6832fa1 100644 --- a/qiskit/transpiler/preset_passmanagers/releasenotes/notes/remove-hard-time-limit-vf2-be83830ecc71f72c.yaml +++ b/qiskit/transpiler/preset_passmanagers/releasenotes/notes/remove-hard-time-limit-vf2-be83830ecc71f72c.yaml @@ -4,7 +4,7 @@ upgrade: The preset pass managers generated by :func:`~.level_1_pass_manager`, :func:`~.level_2_pass_manager`, and :func:`~.level_3_pass_manager` and used by the :func:`~.transpile` function's ``optimization_level`` argument at - 1, 2, and 3 respectively no longer is setting a hard time limit on the + 1, 2, and 3 respectively no longer set a hard time limit on the :class:`~.VF2Layout` transpiler pass. This means that the pass will no longer stop trying to find a better alternative perfect layout up until a fixed time limit (100ms for level 1, 10 sec for level 2, and 60 sec for