Skip to content

Accumulate ParallelLinearQubitOperator matvecs in-place (#1410) - #1450

Merged
mhucka merged 2 commits into
quantumlib:mainfrom
rosspeili:fix/issue-1410-matvec-inplace-accumulate
Sep 7, 2026
Merged

mhucka merged 2 commits into
quantumlib:mainfrom
rosspeili:fix/issue-1410-matvec-inplace-accumulate

Conversation

@rosspeili

Copy link
Copy Markdown
Contributor

Implements the suggestion from #1410: avoid functools.reduce(numpy.add, …) when combining partial matvecs, which was allocating a new full-sized array for every partial sum.

Used the approach from GCA and went a bit further:

  • Shared in-place += accumulation for both the single-process and multiprocess paths (same cost when combining worker results).
  • Only set forkserver when processes > 1, so the single-process path works on Windows.

There is one nuance with processes=1, where operator grouping usually yields a single group so the biggest + is on the multiprocess reduce. Happy to trim or adjust if its better to keep the change scoped only to the single-process path.

Tests passed, and will wait for CI to see if I missed anything.

Fixes #1410

…antumlib#1410)

Accumulate partial matvecs into one buffer with in-place += instead of functools.reduce(numpy.add), for both the single-process and multiprocess paths. Defer forkserver setup until processes > 1 so the single-process path works on Windows.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request optimizes memory usage and improves platform compatibility for ParallelLinearQubitOperator. It replaces functools.reduce(numpy.add, ...) with a new helper function _accumulate_vectors that performs in-place vector accumulation to avoid intermediate allocations. Additionally, it ensures that the 'forkserver' multiprocessing start method is only set when spawning multiple processes, allowing the single-process path to run on platforms like Windows. Unit tests have been added to cover the new helper function and the single-process execution path. There are no review comments, so I have no feedback to provide.

@mhucka mhucka self-assigned this Sep 7, 2026
@mhucka mhucka added the area/performance Involves code performance label Sep 7, 2026

@mhucka mhucka left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for this contribution. If you could address a couple of minor items, I think it'll be ready to go after that.

if not ParallelLinearQubitOperator._start_method_set:
# Only required when actually spawning workers; the single-process path
# must remain usable on platforms without forkserver (e.g. Windows).
if self.options.processes > 1 and not ParallelLinearQubitOperator._start_method_set:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the caller passes in an options object that has no processes field or processes = None, this will result in an error. Can you add a defensive check or wrap it in a try-except clause?

Maybe something like

    processes = getattr(self.options, 'processes', None) or 1

and then use processes instead of self.options.processes.

Comment on lines +29 to +32
``functools.reduce(numpy.add, ...)`` builds a new full-sized array for every
partial sum. For large state vectors that creates substantial temporary
memory pressure. Accumulating with in-place ``+=`` keeps a single result
buffer instead.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please switch the use of double backquotes to single backquotes in the docstring.

Use getattr for options.processes with a single-process fallback, and switch the helper docstring to single backticks.
@rosspeili

Copy link
Copy Markdown
Contributor Author

Thanks @mhucka, both addressed, lmk how this looks.

@mhucka mhucka left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this!

@mhucka
mhucka added this pull request to the merge queue Sep 7, 2026
Merged via the queue into quantumlib:main with commit 60a6e1a Sep 7, 2026
23 checks passed
@rosspeili
rosspeili deleted the fix/issue-1410-matvec-inplace-accumulate branch September 7, 2026 16:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/performance Involves code performance

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Possible micro-optimization in linear_qubit_operator.py

2 participants