8000 Embed parallelization into the multi_voxel_fit decorator. by arokem · Pull Request #2593 · dipy/dipy · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Embed parallelization into the multi_voxel_fit decorator. #2593

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

Merged
merged 56 commits into from
Jun 29, 2024

Conversation

arokem
Copy link
Contributor
@arokem arokem commented May 8, 2022

I've started playing around with the idea that the multi_voxel_fit decorator could use paramap instead of iterating over voxels. If we can make this work generally that would be pretty cool. So far, I've only tested this with the fwdti model, and in that case, the change to the additional changes to the code are rather minimal, which gives me hope that we might be able to use this wherever we use this decorator, so in csd, dsi, forecast, fwdti, gqi, ivim, mapmri, mcsd, qtdmri, and shore (!).

@pep8speaks
Copy link
pep8speaks commented May 8, 2022

Hello @arokem, Thank you for updating !

Line 71:31: E203 whitespace before ':'

Comment last updated at 2024-06-29 20:43:35 UTC

@skoudoro
Copy link
Member
skoudoro commented May 8, 2022

Thank you for starting this @arokem!

Have you looked at #1418? I think some ideas can be reused here.

@arokem
Copy link
Contributor Author
arokem commented May 8, 2022 via email

@codecov
Copy link
codecov bot commented May 9, 2022

Codecov Report

Attention: Patch coverage is 80.43478% with 9 lines in your changes missing coverage. Please review.

Project coverage is 83.64%. Comparing base (5fc3d44) to head (b2a381a).

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #2593      +/-   ##
==========================================
- Coverage   83.65%   83.64%   -0.02%     
==========================================
  Files         152      152              
  Lines       21374    21395      +21     
  Branches     3459     3465       +6     
==========================================
+ Hits        17881    17895      +14     
- Misses       2629     2636       +7     
  Partials      864      864              
Files Coverage Δ
dipy/reconst/csdeconv.py 87.42% <100.00%> (ø)
dipy/reconst/dsi.py 80.21% <100.00%> (ø)
dipy/reconst/forecast.py 92.82% <100.00%> (ø)
dipy/reconst/fwdti.py 94.28% <100.00%> (ø)
dipy/reconst/gqi.py 54.00% <100.00%> (ø)
dipy/reconst/ivim.py 96.00% <100.00%> (ø)
dipy/reconst/mapmri.py 92.09% <100.00%> (ø)
dipy/reconst/mcsd.py 88.69% <100.00%> (ø)
dipy/reconst/qtdmri.py 93.38% <100.00%> (ø)
dipy/reconst/shore.py 91.90% <100.00%> (ø)
... and 2 more

@arokem
Copy link
Contributor Author
arokem commented May 9, 2022

I ran a benchmark on a beefy 24-cpu compute server with the recent commit.I get a roughly 13x speedup for fitting the fwdti model with engine="joblib" relative to the default serial mode. I should maybe mention that the server is also doing a bunch of other work, so it's not the cleanest benchmark, but still quite promising.

@arokem arokem changed the title WIP: Embed parallelization into the multi_voxel_fit decorator. Embed parallelization into the multi_voxel_fit decorator. May 9, 2022
@arokem
Copy link
Contributor Author
arokem commented May 16, 2022

Does anyone understand why half the CI actions are still pending? They have been pending since Friday!

@skoudoro
Copy link
Member

No, but I will restart them first

@skoudoro
Copy link
Member

Hi @arokem,

It seems we have a new issue with DIPY installation. I do not know yet what changes. the CI's are failing in all PR.
I will start to dig into it

@arokem arokem force-pushed the para_multivoxel branch from 892d26c to 7628a78 Compare May 17, 2022 16:09
@arokem
Copy link
Contributor Author
arokem commented May 17, 2022

Just rebased on top of #2595

@arokem
Copy link
Contributor Author
arokem commented May 18, 2022

Does anyone understand these CI failures? I don't think they are related to the content of the PR, but I might be missing something.

@skoudoro
Copy link
Member

Does anyone understand these CI failures? I don't think they are related to the content of the PR, but I might be missing something.

Both failures are on the parallelization CI's with a memory leaks issue. This might be due to some of the parallel packages that might change some environment variable flags. These flags could have an impact on this parallelized function.

All supposition, this is what comes first to my mind.

@skoudoro
Copy link
Member

the failing function are using openmp

@arokem arokem force-pushed the para_multivoxel branch from 7628a78 to a9b3c2f Compare May 28, 2022 05:07
@arokem
Copy link
Contributor Author
arokem commented May 29, 2022

Hey @skoudoro, I noticed that you did not pin the ray version in #2600, instead pinning only protobuf, but I am seeing this again on the CI: https://github.com/dipy/dipy/runs/6634820045?check_suite_focus=true#step:9:119, which suggests to me that I should pin ray to 0.11 for now. Does that make sense to you? I'll give it a try here.

@arokem
Copy link
Contributor Author
arokem commented May 29, 2022

Or possibly 1.11.1

@arokem arokem force-pushed the para_multivoxel branch from 48f7b3f to 8d7f71b Compare May 30, 2022 02:53
@arokem
Copy link
Contributor Author
arokem commented May 30, 2022

We're back to this failure: https://github.com/dipy/dipy/runs/6645881563?check_suite_focus=true#step:9:3751

Interestingly, I can't get this to fail locally on my machine (in an env with dask, ray and joblib installed). I also don't exactly understand how this is related to openmp. Does set_number_of_points use openmp?

single_voxel_with_self = partial(single_voxel_fit, self)
n_jobs = kwargs.get("n_jobs", multiprocessing.cpu_count() - 1)
vox_per_chunk = np.max([data_to_fit.shape[0] // n_jobs, 1])
chunks = [data_to_fit[ii:ii + vox_per_chunk]
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This might duplicate memory. Need to benchmark.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@arokem
Copy link
Contributor Author
arokem commented Dec 13, 2022

Plan to make progress here:

  • Set up experimental datasets: All of the models except for DSI can use multi-shell data. Only CSD (I think) can run on single-shell data. For multi-shell datasets we can use HBN and HCP. For DSI, I guess we can use the dsi dataset we have in our data fetchers. We'll need to set up fetchers for HBN data (see Replace CENIR multishell with HBN POD2 data #2695) and for HCP (see Port HCP fetcher from pyAFQ into here #2696).

  • Set up experimental scripts (separate repo, probably): these should run every one of the models that are decorated in this PR with:
    1. Serial mode.
    2. Parallelized by voxel with dask, ray, joblib.
    3. Parallelized by chunk with dask, ray, joblib.
    4. Parallelized with different backends if possible.
    5. For ray/dask, parallelize on a big distributed AWS cluster.

  • Run the experiments. We'll need to have some uniform hardware settings. We'll want to run this on different OS (Windows, Linux, Mac OS) and maybe on different kinds of computational architectures (e.g., distributed cluster vs. one big machine).

  • Separately benchmark timing (this is straightforward) and memory (using https://github.com/pythonprofilers/memory_profiler).

  • Compare and contrast 😄

Copy link
Member
@skoudoro skoudoro left a comment

Choose a reason for hiding this comment

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

For now, it works with `engin in ["serial", "dask"]

  • my laptop crash with ray
  • See below for joblib issue.

I will share the timing when those 2 are fixed.

Thanks @arokem

_parallel_fit_worker,
chunks,
func_args=[single_voxel_with_self],
**kwargs)
Copy link
Member

Choose a reason for hiding this comment

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

dask did not complain but joblib fails with this:

TypeError: __init__() got an unexpected keyword argument 'vox_per_chunk'

we need to update paramap function

@skoudoro skoudoro force-pushed the master branch 5 times, most recently from 7e158ff to dda2ffa Compare December 8, 2023 16:00
@arokem arokem force-pushed the para_multivoxel branch from 0140c8c to 79b13ef Compare June 27, 2024 22:24
@arokem
Copy link
Contributor Author
arokem commented Jun 27, 2024

Rebased. Could you help me with the CI? I am not sure how to check that we're in the "optional" case.

Copy link
Member
@skoudoro skoudoro left a comment

Choose a reason for hiding this comment

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

Rebased. Could you help me with the CI? I am not sure how to check that we're in the "optional" case.

Thanks! It should be something like the suggestion below. I hope there is no typo in this syntax

Co-authored-by: Serge Koudoro <skab12@gmail.com>
@arokem
Copy link
Contributor Author
arokem commented Jun 28, 2024 via email

Copy link
Member
@skoudoro skoudoro left a comment

Choose a reason for hiding this comment

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

Hi @arokem,

I was going to merge but I saw that a previous comment has been remove but not addressed. see below the suggestion and then I can go ahead.

Thank you

arokem and others added 2 commits June 29, 2024 13:43
Co-authored-by: Serge Koudoro <skab12@gmail.com>
Co-authored-by: Serge Koudoro <skab12@gmail.com>
@arokem
Copy link
Contributor Author
arokem commented Jun 29, 2024

Sorry about that and thanks for spotting this.

Copy link
Member
@skoudoro skoudoro left a comment

Choose a reason for hiding this comment

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

okay, all good, I will go ahead and merge this PR.

Thank you for this amazing work @arokem and @asagilmore!

NOTE: we need to document it in details somewhere. It will take time. So, for now, I recommend a follow-up PR to add a small recipe in dipy documentation (see https://docs.dipy.org/stable/recipes). Just add a small section: How to accelerate the fitting in all DIPY reconstruction models? or something similar.

We're writing up a report about this here and we'd be happy to have input on the results and ideas that we are developing there (the repo for that report is here: https://github.com/nrdg/2024-dipy-parallelization).

Where can we find the comparison with joblib, dask and ray? I see a lot of work with Ray and this is clearly the recommended backend. However, it would be great to see the advantage against the others backend. Thank you for your feedback

@skoudoro skoudoro merged commit 6c59e39 into dipy:master Jun 29, 2024
30 of 31 checks passed
@skoudoro
Copy link
Member
skoudoro commented Jul 2, 2024

Following up with my questions above @arokem and @asagilmore

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

Successfully merging this pull request may close these issues.

6 participants
0