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
ENH: Faster numpy.save and numpy.load #22898
Comments
What NumPy version is that? |
The latest one for both platforms, on recent machines and OS, same speed difference on both: Windows 11, Python 3.9.12 x64, Numpy 1.24.0, Intel Core i7-12700K:
macOS 12.5, Python 3.9.15 arm64, Numpy 1.24.0, Apple M1:
See https://github.com/divideconcept/fastnumpyio for more details about the benchmark and implementation. |
Hi everybody, great to see some more effort in this topic 🤩 Your demo definitely shows how easy handling
https://numpy.org/neps/nep-0001-npy-format.html One could try to find the bottleneck. Maybe it can be fixed easily by modifying some lines here and there. Meanwhile, maybe https://github.com/xor2k/npy-append-array could help you out. I mostly use it by putting all the data into one big |
Btw. I've just seen quite an interesting talk regarding |
Thanks for the references, I'll have a look. To me the whole bottleneck of numpy.save/numpy.load (specially numpy.load) is that the .npy format has an ascii header with a lot of possible combinations. It's great to have this flexibility, but I'm pretty sure 99% of numpy users just use plain simple arrays, without data nesting, fortran ordering or labelling, and just npy format version 1.0 - and trying to parse this header fully for all possible cases is just a waste of time for the vast majority of numpy users. To speed up loading in that case, there should be a quick detector at the start of numpy.load to check if we're dealing with a simple array or something more complex. This can be achieved with a simple character detection in the header text, for example count the number of : ' and (. If it's a simple header go with quick parsing, if not do the full parsing. |
|
I have implemented this, pull request see #22916 Here some new benchmarks (different machine, don't compare to the images above): Times without using cProfile (more realistic):
Times without using cProfile (more realistic):
|
Here for comparison a hypothetical case when using JSON for header encoding/decoding (same machine as in comment before): Times without using cProfile (more realistic):
|
I won't disagree that it would be nice to use json (eventually?), but how do you ensure forward compatibility (old versions loading newly generated files)? It also may be non-trivial for dtypes with fields. |
This is a future topic. The test itsself was easy to do, so I just did it. I'll open a new issue then, let's first finish this one 😅 |
This pull requests speeds up numpy.load. Since _filter_header is quite a bottleneck, we only run it if we must. Users will get a warning if they have a legacy Numpy file so that they can save it again for faster loading. Main discussion and benchmarks see #22898 Co-authored-by: Sebastian Berg <sebastian@sipsolutions.net>
Proposed new feature or change:
I find numpy.save and numpy.load quite slow, in particular with small arrays, which can become a bottleneck when dealing with large datasets in machine learning.
I came up with faster save/load routines for simple arrays (standard dtypes, no Fortran ordering or nested/labelled data) - which probably represents the vast majority of use cases: https://github.com/divideconcept/fastnumpyio
Maybe there's a way to optimize numpy.save()/numpy.load() npy header parsing for simple arrays ?
The text was updated successfully, but these errors were encountered: