From 88ae00cf1a07aa8eb73e1c0062c3d16603e46f8c Mon Sep 17 00:00:00 2001 From: Will Shanks Date: Tue, 19 Mar 2024 16:32:50 -0400 Subject: [PATCH] Serialize CompositeAnalysis execution CompositeAnalysis was calling run() on each subcomponent, which starts a new thread for each one, and then waiting on all of them to finish. Because of the way Python executes threads only one thread executes Python code at a time and there is not much performance benefit to starting all the threads at once. Here, the code is changed to wait for each subcomponent's run() to complete before starting the next one. Executing sequentially like this avoids starting an uncontrolled numbers of threads simultaneously. This is a temporary mitigation and a wider refactor should be done to handle analysis execution better. --- .../framework/composite/composite_analysis.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/qiskit_experiments/framework/composite/composite_analysis.py b/qiskit_experiments/framework/composite/composite_analysis.py index fb04ba50f9..0ec98eed89 100644 --- a/qiskit_experiments/framework/composite/composite_analysis.py +++ b/qiskit_experiments/framework/composite/composite_analysis.py @@ -149,12 +149,15 @@ def _run_analysis(self, experiment_data: ExperimentData): # Since copy for replace result is handled at the parent level # we always run with replace result on component analysis self._analyses[i].run(sub_expdata, replace_results=True) - - # Analysis is running in parallel so we add loop to wait - # for all component analysis to finish before returning - # the parent experiment analysis results - for sub_expdata in component_expdata: + # Block for results to avoid issues nested CompositeAnalysis runs. + # Ideally this constraint will be removed in the future. + # Previously run() was called on all components and then + # block_for_results() was called on all of them, but since only one + # thread can execute Python code at a time there is not much + # difference in performance. Blocking separately limits the number + # of threads that are started simultaneously. sub_expdata.block_for_results() + # Optionally flatten results from all component experiments # for adding to the main experiment data container if self._flatten_results: