read_h5ad backed mode still runs out of memory on large datasets
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 2.6k
- Forks
- 779
- Avg merge
- 1d 4h
- Merged PRs (30d)
- 27
Description
- I have checked that this issue has not already been reported.
- I have confirmed this bug exists on the latest version of scanpy.
- (optional) I have confirmed this bug exists on the master branch of scanpy.
I am not 100% this is a bug, so please correct me if I'm doing something wrong...
I am using scanpy with a very large scRNAseq dataset (SEA-AD, the sparse h5ad is ~35GB)
When I use the read_h5ad file, even when running in backed mode, I get an out of memory exception.
I expect it to be due to the fact that parts of the dataset are still read to memory, even in backed mode.
As you can see in the stack trace below, eventually anndata's read_sparse() function is called (in _io/specs/methods.py
But this method has the following implementation in the latest version:
def read_sparse(elem):
return SparseDataset(elem).to_memory()
Thus, loading (part of) the dataset to memory.
Like I said, I am not sure whether this is a bug, or supposed to happen. But to me it seems odd that backed mode still loads large portions of the dataset to memory.
Workaround
For my own project, I got around this issue, by removing the call to .to_memory() within the source of anndata. I am not sure whether this breaks any other functionality, but I can use the dataset the way I need it right now.
Minimal code sample (that we can copy&paste without having any data)
(this cannot be run without any data, because the problem is that it fails with a big dataset. I included an aws download command to the big dataset that is causing the crash on my 24GB memory machine)
import scanpy
# Download command
# aws s3 cp --no-sign-request s3://sea-ad-single-cell-profiling/MTG/RNAseq/SEAAD_MTG_RNAseq_final-nuclei.2022-08-18.h5ad ./final.h5ad
PATH = './final.h5py'
adata = scanpy.read_h5ad(PATH, backed=True)
(the stack trace below was redacted a bit to hide my private information. [python-path] replaces the path to pythons directory)
Traceback (most recent call last):
File "scanpy_test.py", line 9, in <module>
adata = sc.read_h5ad(PATH, backed=True)
File "[python-path]\site-packages\anndata\_io\h5ad.py", line 202, in read_h5ad
return read_h5ad_backed(filename, mode)
File "[python-path]\site-packages\anndata\_io\h5ad.py", line 146, in read_h5ad_backed
d.update({k: read_elem(f[k]) for k in attributes if k in f})
File "[python-path]\site-packages\anndata\_io\h5ad.py", line 146, in <dictcomp>
d.update({k: read_elem(f[k]) for k in attributes if k in f})
File "[python-path]\site-packages\anndata\_io\specs\registry.py", line 183, in read_elem
return _REGISTRY.get_reader(type(elem), get_spec(elem), frozenset(modifiers))(elem)
File "[python-path\site-packages\anndata\_io\specs\methods.py", line 92, in read_basic
return {k: read_elem(v) for k, v in elem.items()}
File "[python-path]\site-packages\anndata\_io\specs\methods.py", line 92, in <dictcomp>
return {k: read_elem(v) for k, v in elem.items()}
File "[python-path]\site-packages\anndata\_io\specs\registry.py", line 183, in read_elem
return _REGISTRY.get_reader(type(elem), get_spec(elem), frozenset(modifiers))(elem)
File "[python-path]\site-packages\anndata\_io\specs\methods.py", line 475, in read_sparse
return SparseDataset(elem).to_memory()
File "[python-path]\site-packages\anndata\_core\sparse_dataset.py", line 380, in to_memory
mtx.indices = self.group["indices"][...]
File "h5py\_objects.pyx", line 54, in h5py._objects.with_phil.wrapper
File "h5py\_objects.pyx", line 55, in h5py._objects.with_phil.wrapper
File "[python-path]\site-packages\h5py\_hl\dataset.py", line 741, in __getitem__
return self._fast_reader.read(args)
File "h5py\_selector.pyx", line 362, in h5py._selector.Reader.read
File "h5py\_selector.pyx", line 336, in h5py._selector.Reader.make_array
numpy.core._exceptions._ArrayMemoryError: Unable to allocate 56.8 GiB for an array with shape (7621750342,) and data type int64
Process finished with exit code 1
Versions
anndata 0.8.0
scanpy 1.9.1
PIL 9.2.0
beta_ufunc NA
binom_ufunc NA
colorama 0.4.5
console_thrift NA
cycler 0.10.0
cython_runtime NA
dateutil 2.8.2
h5py 3.7.0
hypergeom_ufunc NA
joblib 1.2.0
kiwisolver 1.4.4
llvmlite 0.39.1
matplotlib 3.6.0
mpl_toolkits NA
natsort 8.2.0
nbinom_ufunc NA
nt NA
numba 0.56.2
numpy 1.22.3
packaging 21.3
pandas 1.4.1
pkg_resources NA
pydev_console NA
pydev_ipython NA
pydevconsole NA
pydevd_file_utils NA
pydevd_plugins NA
pydevd_tracing NA
pyparsing 3.0.7
pytz 2022.1
scipy 1.8.0
session_info 1.0.0
sitecustomize NA
six 1.16.0
sklearn 1.1.2
threadpoolctl 3.1.0
Python 3.10.2 (tags/v3.10.2:a58ebcc, Jan 17 2022, 14:12:15) [MSC v.1929 64 bit (AMD64)]
Windows-10-10.0.22000-SP0
Session information updated at 2022-10-26 15:35
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with scanpy.read_h5ad(..., backed=True), then inspect anndata/_io/specs/methods.py at read_sparse and anndata/_core/sparse_dataset.py at to_memory. Reproduce with the large SEA-AD h5ad example and verify that backed loading no longer attempts the reported 56.8 GiB allocation while preserving expected dataset access.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- bioinformatics
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100