在内存映射模式下尝试 cupy.load 更大尺寸的 .npy 文件时出现 Cupy OutOfMemoryError,但 np.load 工作正常

Cupy OutOfMemoryError when trying to cupy.load larger dimension .npy files in memory map mode, but np.load works fine

我正在尝试使用内存映射模式在 cupy 中加载一些较大的 .npy 文件,但我将 运行 保留为 OutOfMemoryError

我认为既然它是在内存映射模式下打开的,这个操作应该不会占用太多内存,因为内存映射实际上不会将整个数组加载到内存中。

我可以用 np.load 加载这些文件就好了,这似乎只发生在 cupy.load 上。我的环境是 Google Colab,使用 Tesla K80 GPU。它有大约 12 GB CPU 内存、12 GB GPU 内存和 350 GB 磁盘 space。

这是重现错误的最小示例:

import os
import numpy as np
import cupy

#Create .npy files. 
for i in range(4):
    numpyMemmap = np.memmap( 'reg.memmap'+str(i), dtype='float32', mode='w+', shape=( 10000000 , 128 ))
    np.save( 'reg.memmap'+str(i) , numpyMemmap )
    del numpyMemmap
    os.remove( 'reg.memmap'+str(i) )

# Check if they load correctly with np.load.
NPYmemmap = []
for i in range(4):
    NPYmemmap.append( np.load( 'reg.memmap'+str(i)+'.npy' , mmap_mode = 'r+' )  )
del NPYmemmap

# Eventually results in memory error. 
CPYmemmap = []
for i in range(4):
    print(i)
    CPYmemmap.append( cupy.load( 'reg.memmap'+str(i)+'.npy' , mmap_mode = 'r+' )  )

输出:

0
1
/usr/local/lib/python3.6/dist-packages/cupy/creation/from_data.py:41: UserWarning: Using synchronous transfer as pinned memory (5120000000 bytes) could not be allocated. This generally occurs because of insufficient host memory. The original error was: cudaErrorMemoryAllocation: out of memory
  return core.array(obj, dtype, copy, order, subok, ndmin)
2
3
---------------------------------------------------------------------------
OutOfMemoryError                          Traceback (most recent call last)
<ipython-input-4-b5c849e2adba> in <module>()
      2 for i in range(4):
      3     print(i)
----> 4     CPYmemmap.append( cupy.load( 'reg.memmap'+str(i)+'.npy' , mmap_mode = 'r+' )  )

1 frames
/usr/local/lib/python3.6/dist-packages/cupy/io/npz.py in load(file, mmap_mode)
     47     obj = numpy.load(file, mmap_mode)
     48     if isinstance(obj, numpy.ndarray):
---> 49         return cupy.array(obj)
     50     elif isinstance(obj, numpy.lib.npyio.NpzFile):
     51         return NpzFile(obj)

/usr/local/lib/python3.6/dist-packages/cupy/creation/from_data.py in array(obj, dtype, copy, order, subok, ndmin)
     39 
     40     """
---> 41     return core.array(obj, dtype, copy, order, subok, ndmin)
     42 
     43 

cupy/core/core.pyx in cupy.core.core.array()

cupy/core/core.pyx in cupy.core.core.array()

cupy/core/core.pyx in cupy.core.core.ndarray.__init__()

cupy/cuda/memory.pyx in cupy.cuda.memory.alloc()

cupy/cuda/memory.pyx in cupy.cuda.memory.MemoryPool.malloc()

cupy/cuda/memory.pyx in cupy.cuda.memory.MemoryPool.malloc()

cupy/cuda/memory.pyx in cupy.cuda.memory.SingleDeviceMemoryPool.malloc()

cupy/cuda/memory.pyx in cupy.cuda.memory.SingleDeviceMemoryPool._malloc()

cupy/cuda/memory.pyx in cupy.cuda.memory._try_malloc()

OutOfMemoryError: out of memory to allocate 5120000000 bytes (total 20480000000 bytes)

我也想知道这是否可能与 Google Colab 及其 enviroment/GPU 有关。

为方便起见,这里有一个 Google 这个最小代码的 Colab 笔记本

https://colab.research.google.com/drive/12uPL-ZnKhGTJifZGVdTN7e8qBRRus4tA

内存映射时磁盘文件的 numpy.load 机制可能不需要将整个文件从磁盘加载到主机内存中。

但是 cupy.load 似乎要求整个文件首先适合主机内存,然后适合设备内存。

您的特定测试用例似乎正在创建 4 个大小约为 5GB 的磁盘文件。如果您每个都有 12GB,那么它们将无法全部放入主机或设备内存中。因此,我希望在第三次文件加载时失败,如果不是更早的话。

可以使用带有映射内存的 numpy.load 机制,然后使用 cupy 操作有选择地将部分数据移动到 GPU。在那种情况下,GPU 上的数据大小仍将限制在 GPU RAM 内,用于 cupy 数组等常见事物。

即使您可以使用 CUDA 固定 "zero-copy" 内存,它仍然会受到主机内存大小(此处为 12GB)或更少的限制。