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

Embed parallelization into the multi_voxel_fit decorator. #2593

Open
wants to merge 50 commits into
base: master
Choose a base branch
from

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 !

Cheers ! There are no PEP8 issues in this Pull Request. 🍻

Comment last updated at 2024-05-16 04:28:10 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.85106% with 9 lines in your changes are missing coverage. Please review.

Project coverage is 83.72%. Comparing base (f741b88) to head (f593491).
Report is 5 commits behind head on master.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #2593      +/-   ##
==========================================
- Coverage   83.75%   83.72%   -0.04%     
==========================================
  Files         153      153              
  Lines       21343    21364      +21     
  Branches     3445     3451       +6     
==========================================
+ Hits        17876    17887      +11     
- Misses       2611     2620       +9     
- Partials      856      857       +1     
Files Coverage Δ
dipy/reconst/csdeconv.py 87.38% <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.56% <100.00%> (ø)
dipy/reconst/shore.py 91.90% <100.00%> (ø)
... and 2 more

... and 1 file with indirect coverage changes

@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
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
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
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
Copy link
Contributor Author

arokem commented Apr 23, 2024

The errors on the CI are really puzzling and hard to reproduce locally and we worry that it might be some funky interaction with joblib, so I am removing the multi_voxel decorator for that model and we can reinstate it on a separate PR later on, if we fix everything else here.

@arokem
Copy link
Contributor Author

arokem commented Apr 23, 2024

OK - having removed the decorator from the SFM model, it seems that the only remaining error on the CI is completely unrelated. Or am I missing something?

@arokem
Copy link
Contributor Author

arokem commented Apr 23, 2024

At any rate, @asagilmore has now completed an extensive set of experiments with this PR and we are glad to say that Ray in particular provides a substantial speedup for reconstruction models (on the order of 10x) across two different models, and across a pretty wide range of hardware setups and chunking schemes. 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).

With that said, I think that this code and the results we report are ready for a review, and are hopefully close to a shape where they can be merged for an upcoming release.

@arokem
Copy link
Contributor Author

arokem commented Apr 26, 2024

Looks like installing pytables on mac is (newly?) broken: https://github.com/dipy/dipy/actions/runs/8847440312/job/24295269319?pr=2593#step:6:125

@skoudoro
Copy link
Member

Yes, I saw that with pytable.

Not sure what we can do apart from reporting.

The last release was 6month ago so not sure what changed last week.

Maybe a release of h5py...

@arokem
Copy link
Contributor Author

arokem commented Apr 26, 2024

There was one on April 10th: https://pypi.org/project/h5py/3.11.0/

I'm trying to pin to 3.10 in cd0e653. Let's see what we learn.

@arokem
Copy link
Contributor Author

arokem commented Apr 26, 2024

Following #3202, what's the right way to catch a warning thrown when importing one of the optional dependencies? I am getting:

reconst/tests/test_multi_voxel.py::test_multi_voxel_fit
  /home/runner/work/dipy/dipy/venv/lib/python3.10/site-packages/ray/_private/pydantic_compat.py:2: DeprecationWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html
    from pkg_resources import packaging

reconst/tests/test_multi_voxel.py::test_multi_voxel_fit
  /home/runner/work/dipy/dipy/venv/lib/python3.10/site-packages/pkg_resources/__init__.py:2832: DeprecationWarning: Deprecated call to `pkg_resources.declare_namespace('google')`.
  Implementing implicit namespace packages (as specified in PEP 420) is preferred to `pkg_resources.declare_namespace`. See https://setuptools.pypa.io/en/latest/references/keywords.html#keyword-namespace-packages
    declare_namespace(pkg)

I believe this is emitted when importing ray. Should I explicitly ignore it in a context manager around that import?

@skoudoro
Copy link
Member

The "right way" would be to add the warning message with ignore status in the pyproject.toml.

see here:

dipy/pyproject.toml

Lines 184 to 186 in 60669b8

filterwarnings = [
'ignore:.*You do not have FURY installed.*:UserWarning',
]

@skoudoro
Copy link
Member

skoudoro commented Apr 26, 2024

if it is too much for the pyproject.toml, we could add/create a specific python file for that.

@skoudoro
Copy link
Member

skoudoro commented Apr 26, 2024

For example, mne-python do it directly in the conftest.py instead of the pyproject.toml.

see here: https://github.com/mne-tools/mne-python/blob/main/mne/conftest.py#L131-L178

So, this is something to decide together, what is your opinion @arokem and @jhlegarreta ?

@arokem
Copy link
Contributor Author

arokem commented Apr 26, 2024

I like it better in the conftest

@jhlegarreta
Copy link
Contributor

Hats off for this work, Ariel.

So, this is something to decide together, what is your opinion @arokem and @jhlegarreta ?

Having filtering rules both in the pyproject.toml and the conftest.py file would make things easier to follow, as we would need to look at two files instead of one. Also, not sure if pytest would end up by overriding the rules in one file by the ones that it reads in the last place.

So probably as Serge says, if the list of rules becomes too lengthy, better to keep them all in the conftest.py file.

@skoudoro
Copy link
Member

OK, thank you for your feedback @arokem and @jhlegarreta.

I will create a PR later today to update that. Also, I think we should add it to the developer guide concerning the warnings policy.

@arokem
Copy link
Contributor Author

arokem commented Apr 26, 2024

Thanks! I will wait for your PR to see how this is done.

In the meanwhile, it doesn't look like pinning h5py helped with the pytables installation.

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.

None yet

5 participants