From 11b290e577ee134cc18579d489536e12a76eca0c Mon Sep 17 00:00:00 2001 From: Matthew Treinish Date: Fri, 5 Apr 2024 16:59:45 -0400 Subject: [PATCH] Increase heuristic effort for optimization level 2 This commit tweaks the heuristic effort in optimization level 2 to be more of a middle ground between level 1 and 3; with a better balance between output quality and runtime. This places it to be a better default for a pass manager we use if one isn't specified. The tradeoff here is that the vf2layout and vf2postlayout search space is reduced to be the same as level 1. There are diminishing margins of return on the vf2 layout search especially for cases when there are a large number of qubit permutations for the mapping found. Then the number of sabre trials is brought up to the same level as optimization level 3. As this can have a significant impact on output and the extra runtime cost is minimal. The larger change is that the optimization passes from level 3. This ends up mainly being 2q peephole optimization. With the performance improvements from #12010 and #11946 and all the follow-on PRs this is now fast enough to rely on in optimization level 2. --- .../preset_passmanagers/builtin_plugins.py | 35 ++++++------------- .../transpiler/preset_passmanagers/common.py | 7 +--- 2 files changed, 12 insertions(+), 30 deletions(-) diff --git a/qiskit/transpiler/preset_passmanagers/builtin_plugins.py b/qiskit/transpiler/preset_passmanagers/builtin_plugins.py index a5aa9fa44957..cdd2d989c786 100644 --- a/qiskit/transpiler/preset_passmanagers/builtin_plugins.py +++ b/qiskit/transpiler/preset_passmanagers/builtin_plugins.py @@ -87,7 +87,7 @@ def pass_manager(self, pass_manager_config, optimization_level=None) -> PassMana pass_manager_config.unitary_synthesis_plugin_config, pass_manager_config.hls_config, ) - elif optimization_level in {1, 2}: + elif optimization_level == 1: init = PassManager() if ( pass_manager_config.initial_layout @@ -123,10 +123,8 @@ def pass_manager(self, pass_manager_config, optimization_level=None) -> PassMana ] ) ) - if optimization_level == 2: - init.append(CommutativeCancellation()) - elif optimization_level == 3: + elif optimization_level in {2, 3}: init = common.generate_unroll_3q( pass_manager_config.target, pass_manager_config.basis_gates, @@ -543,18 +541,7 @@ def _opt_control(property_set): ] ), ] - elif optimization_level == 2: - # Steps for optimization level 2 - _opt = [ - Optimize1qGatesDecomposition( - basis=pass_manager_config.basis_gates, target=pass_manager_config.target - ), - CommutativeCancellation( - basis_gates=pass_manager_config.basis_gates, - target=pass_manager_config.target, - ), - ] - elif optimization_level == 3: + elif optimization_level in {2, 3}: # Steps for optimization level 3 _opt = [ Collect2qBlocks(), @@ -596,13 +583,13 @@ def _unroll_condition(property_set): ConditionalController(unroll, condition=_unroll_condition), ] - if optimization_level == 3: + if optimization_level in {2, 3}: optimization.append(_minimum_point_check) else: optimization.append(_depth_check + _size_check) opt_loop = ( _opt + _unroll_if_out_of_basis + _minimum_point_check - if optimization_level == 3 + if optimization_level in {2, 3} else _opt + _unroll_if_out_of_basis + _depth_check + _size_check ) optimization.append(DoWhileController(opt_loop, do_while=_opt_control)) @@ -746,10 +733,10 @@ def _swap_mapped(property_set): choose_layout_0 = VF2Layout( coupling_map=pass_manager_config.coupling_map, seed=pass_manager_config.seed_transpiler, - call_limit=int(5e6), # Set call limit to ~10s with rustworkx 0.10.2 + call_limit=int(5e4), # Set call limit to ~10s with rustworkx 0.10.2 properties=pass_manager_config.backend_properties, target=pass_manager_config.target, - max_trials=25000, # Limits layout scoring to < 10s on ~400 qubit devices + max_trials=2500, # Limits layout scoring to < 10s on ~400 qubit devices ) layout.append( ConditionalController(choose_layout_0, condition=_choose_layout_condition) @@ -758,8 +745,8 @@ def _swap_mapped(property_set): coupling_map, max_iterations=2, seed=pass_manager_config.seed_transpiler, - swap_trials=10, - layout_trials=10, + swap_trials=20, + layout_trials=20, skip_routing=pass_manager_config.routing_method is not None and pass_manager_config.routing_method != "sabre", ) @@ -911,8 +898,8 @@ def _swap_mapped(property_set): coupling_map, max_iterations=2, seed=pass_manager_config.seed_transpiler, - swap_trials=10, - layout_trials=10, + swap_trials=20, + layout_trials=20, skip_routing=pass_manager_config.routing_method is not None and pass_manager_config.routing_method != "sabre", ) diff --git a/qiskit/transpiler/preset_passmanagers/common.py b/qiskit/transpiler/preset_passmanagers/common.py index dcd9f27c2bc0..1b77e7dbd269 100644 --- a/qiskit/transpiler/preset_passmanagers/common.py +++ b/qiskit/transpiler/preset_passmanagers/common.py @@ -627,16 +627,11 @@ def get_vf2_limits( """ limits = VF2Limits(None, None) if layout_method is None and initial_layout is None: - if optimization_level == 1: + if optimization_level in {1, 2}: limits = VF2Limits( int(5e4), # Set call limit to ~100ms with rustworkx 0.10.2 2500, # Limits layout scoring to < 600ms on ~400 qubit devices ) - elif optimization_level == 2: - limits = VF2Limits( - int(5e6), # Set call limit to ~10 sec with rustworkx 0.10.2 - 25000, # Limits layout scoring to < 6 sec on ~400 qubit devices - ) elif optimization_level == 3: limits = VF2Limits( int(3e7), # Set call limit to ~60 sec with rustworkx 0.10.2