Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Leverage multiprocessing in sample scripts #64

Open
jngrad opened this issue May 24, 2024 · 0 comments
Open

Leverage multiprocessing in sample scripts #64

jngrad opened this issue May 24, 2024 · 0 comments

Comments

@jngrad
Copy link
Member

jngrad commented May 24, 2024

Several sample scripts and functional tests spend most of their runtime in a hot loop that iterates over a pH range and starts independent simulations, typically via a subprocess. These are ideal candidates for parallelization, since the intermediate simulations do not share information with one another and can be executed in any order.

For illustration, consider the dialysis test and its modified version in 166baf4: the original runtime is 10 min, which goes down to 5 min 30s with 2 threads or 3 min 30s with 4 threads. The runtime is not always perfectly divided by the number of threads, because some pH values require longer sampling. GitHub Actions have 2 CPU cores, but since we use a Makefile to schedule Python tests, we can only run one test at a time. Running the long tests with 2 cores could help shave off 10 to 15 min in the biweekly CI.

Adapting existing scripts to leverage multiprocessing is usually only a matter of moving the body of a for loop into a function that is passed to a multiprocessing pool. There are a few caveats:

  • all print statements need to be removed, since they are printed out in random order, sometimes overlapping one another mid-sentence if the buffer doesn't get flushed fast enough by Python
  • if the script called in a subprocess appends data to a file, multiprocessing cannot be used safely, because when multiple independent processes write to the same file, either the last process will overwrite the data from all other processes, or the file system will lock the file for the first process and all other processes will fail to open the file for writing/appending
  • sometimes the script called by the subprocess also has an embarrassingly parallelizable hot loop, in which case one has to determine whether multiprocessing is more beneficial when running in the innermost or outermost loop
    • typically multiprocessing is more beneficial on the outermost loop, unless the innermost loop has better scaling (e.g. each loop iteration in the subprocess script has the exact same simulation runtime, while the main script doesn't)
    • be careful not to use multiprocessing in both the main script and subprocess script by mistake, otherwise the number of spawn processes will increase dramatically

Users could choose the number of threads with an argparse argument like --threads=8 and a sensible default value like 2 or 4. A larger value like 6 wouldn't really be sound, because on a 4-core machine with hyperthreading enabled (i.e. 8 logical cores), the last 2 threads would land on a hyperthread and compete with the 4 other threads, resulting in a marginal speed-up compared to using just 4 threads. I would personally recommend 4 as the default value1, but I'm open to other suggestions.

Footnotes

  1. I couldn't find market share analysis that were detailed enough to allow me to estimate the median number of physical cores in consumer-grade CPUs in 2024. Nevertheless, Intel and AMD made 4-core CPUs available for desktop computers in 2008, and it's probably reasonable to assume that most desktop computers built after 2020 have 4 or more physical cores. This guess includes recent architectures like Intel i7 12700K and Apple M1, which have a mix of performance cores (high power, high frequency, for gaming and video decoding) and energy-efficient cores (low power, low frequency, for background applications).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant