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

Drastically reduce memory usage during epoching #477

Merged
merged 5 commits into from
Nov 26, 2021

Conversation

hoechenberger
Copy link
Member

@hoechenberger hoechenberger commented Nov 26, 2021

Peak memory consumption during epoching reduced by more than 50%!
And we're also faster now!

Benchmarks

Epochs creation during make_epochs script

main

Screen Shot 2021-11-26 at 10 24 14

this branch

Screen Shot 2021-11-26 at 10 24 32

Epochs creation during run_ica script

main

Screen Shot 2021-11-26 at 10 24 53

this branch

Screen Shot 2021-11-26 at 10 25 20

How this was achieved

  • We preload epochs so we can remove the respective raw from memory
  • Instead of creating a list of all epochs for all runs before concatenation and then concatenating them all at once, we now concatenate epochs immediately after they were created. This further reduced peak memory usage significantly (although I don't fully understand why!)
  • During ICA epochs generation, we now drop all epochs that are not in config.conditions. In main, we create epochs from ALL events, often creating uselessly huge numbers of epochs, increasing memory footprint and massively slowing down ICA decomposition.
  • We now only keep a max of 300 EOG and ECG epochs (hardcoded limit)

Further ideas

We may be able to further reduce peak memory consumption at the cost of I/O and processing speed.

  • For example, currently we're creating EOG and ECG epochs in the same loop as the "task" epochs. If we split this into separate loops, peak memory consumption could be lower.
  • Currently, EOG and ECG epochs are reduced to 300 elements only AFTER the bloated epochs objects have been created. Instead, one could first only extract EOG and ECG events, subset those to get 300, and only then create the epochs.

Before merging …

  • Changelog has been updated (docs/source/changes.md)

@hoechenberger hoechenberger changed the title Drastically reduce memory usage during epoching [circle full] Drastically reduce memory usage during epoching Nov 26, 2021
@hoechenberger
Copy link
Member Author

hoechenberger commented Nov 26, 2021

I just disabled EOG and ECG epochs creation during ICA and this is what the mprof looks like then:

Screen Shot 2021-11-26 at 10 56 11

So this is definitely a must-investigate.

@hoechenberger
Copy link
Member Author

Current status during the ICA script, after implementing the changes we discussed during our Zoom call @agramfort

There's still room for improvement but I guess for now it's okay to move on!

Screen Shot 2021-11-26 at 16 26 59

@hoechenberger hoechenberger marked this pull request as ready for review November 26, 2021 15:31
@@ -114,7 +114,7 @@ def make_ecg_epochs(
# (across all runs)
total_ecg_dur = 5 * 60
ecg_dur_per_run = total_ecg_dur / n_runs
t_mid = (raw.times[-1] - raw.times[0]) / 2
t_mid = (raw.times[-1] + raw.times[0]) / 2
Copy link
Member Author

Choose a reason for hiding this comment

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

Ah, good catch! A true mathematician 😁

@hoechenberger hoechenberger merged commit 9a7296e into mne-tools:main Nov 26, 2021
@hoechenberger
Copy link
Member Author

Merci @agramfort!

@hoechenberger hoechenberger deleted the memory branch November 26, 2021 17:34
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

Successfully merging this pull request may close these issues.

None yet

2 participants