pytorch / audio

Data manipulation and transformation for audio signal processing, powered by PyTorch
https://pytorch.org/audio
BSD 2-Clause "Simplified" License
2.43k stars 635 forks source link

Reduce memory usage of forced alignment on CPU #3787

Open MahmoudAshraf97 opened 1 month ago

MahmoudAshraf97 commented 1 month ago

In the forced alignment c++ code, backPtr is an int8 tensor while only storing the values 0,1, and 2 which can be effectively stored using only 2 bits instead of 8, and since the backPtr tensor size is log_probs_len * (targets_length * 2 + 1), it can grow to unmanageable sizes in audio files that exceed 2 hours. By using two std::vector<bool> to represent the two bits needed for backPtr we guarantee that the results are exactly the same while lowering memory usage since std::vector<bool> should use 1 bit to represent a boolean. Best case scenario is memory usage drops to 25%, worst case scenario memory usage doubles if a boolean is represented using 1 byte.

From my experiments, the new code can handle longer audio files without running out of memory. I also noticed that on average, only 1-targets_length/log_probs_length of the backPtr array is used (depending on the inputs) so further memory savings can be gained if we used a shape that reduces unused elements.

log_probs.shape (1,50000,32)
targets.shape (1,25000)
# new code
12.2 s ± 63 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
# original
12.3 s ± 170 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

edit: I implemented a better structure for the backPtr tensor that still uses two boolean vectors but the numbers of elements are greatly reduced to achieve better memory efficiency. The new structure is similar to a sparse matrix or a list of lists, instead of initializing a complete trellis matrix, we initialize the elements which are only going to be used which is approximated by the formula in the code (deduced empirically and tested thorougly). We also create two new arrays for indexing purposes.

pytorch-bot[bot] commented 1 month ago

:link: Helpful Links

:test_tube: See artifacts and rendered test results at hud.pytorch.org/pr/pytorch/audio/3787

Note: Links to docs will display an error until the docs builds have been completed.

This comment was automatically generated by Dr. CI and updates every 15 minutes.

facebook-github-bot commented 1 month ago

Hi @MahmoudAshraf97!

Thank you for your pull request and welcome to our community.

Action Required

In order to merge any pull request (code, docs, etc.), we require contributors to sign our Contributor License Agreement, and we don't seem to have one on file for you.

Process

In order for us to review and merge your suggested changes, please sign at https://code.facebook.com/cla. If you are contributing on behalf of someone else (eg your employer), the individual CLA may not be sufficient and your employer may need to sign the corporate CLA.

Once the CLA is signed, our tooling will perform checks and validations. Afterwards, the pull request will be tagged with CLA signed. The tagging process may take up to 1 hour after signing. Please give it that time before contacting us about it.

If you have received this in error or have any questions, please contact us at cla@meta.com. Thanks!

facebook-github-bot commented 1 month ago

Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Meta Open Source project. Thanks!

vadimkantorov commented 2 weeks ago

I used this compression trick in my Python CTC-based forced alignment: https://github.com/vadimkantorov/ctc/blob/master/ctc.py

And this compression indeed works and helps

MahmoudAshraf97 commented 2 weeks ago

since torchaudio is no longer maintained, I've created a library that builds upon this code and improves it here it's around 50% faster with 5x less memory usage, it also supports all CTC models from hugging face. The MMS alignment model used by torch audio is hosted here