在我看来,当前cupy
没有提供固定的分配器来代替普通的设备内存分配器,即可以用作固定的分配器cupy.ndarray
。如果这对您很重要,那么您可以考虑提出一个冒号的问题。
但是,似乎可以创建一个。这应视为实验代码。并且有一些与其使用相关的问题。
基本思想是,我们将使用cupy.cuda.set_allocator
已经建议的方式,用我们自己的来替换cupy的默认设备内存分配器。我们需要提供自己的替代品,以BaseMemory
用作的存储库cupy.cuda.memory.MemoryPointer
。此处的主要区别在于,我们将使用固定的内存分配器而不是设备分配器。这是PMemory
以下课程的要点。
需要注意的其他事项:
在使用固定的内存(分配)完成所需的操作之后,您可能应该将cupy
分配器恢复为其默认值。不幸的是,与不同cupy.cuda.set_allocator
,我没有找到对应的cupy.cuda.get_allocator
,这使我感到不足cupy
,这似乎也值得向我提出杯状问题。但是,对于本演示,我们将仅返回到None
使用默认设备内存分配器之一的选择(但是不使用池分配器)。
通过提供这种最小的固定内存分配器,我们仍然建议cupy这是普通的设备内存。这意味着不能直接从宿主代码访问它(实际上,但是cupy不知道)。因此,各种操作(例如cupy.load
)将创建不需要的主机分配和不需要的复制操作。我认为解决这个问题将需要的不仅是我建议的小改变。但至少对于您的测试用例,此额外开销可能是可管理的。看来您想一次从磁盘加载数据,然后将其保留在那里。对于这种类型的活动,这应该是可管理的,尤其是因为您将其分为多个部分。就像我们将看到的那样,对于25GB的主机内存来说,处理四个5GB的块实在太多了。我们将需要为四个5GB块(实际上是固定的)分配主机内存,并且还需要一个额外的5GB“开销”缓冲区的额外空间。因此25GB不足以实现这一目标。但是出于演示目的,
与cupy的默认设备内存分配器关联的普通设备内存与特定设备有关联。固定的内存不必具有这样的关联,但是BaseMemory
用类似的类对我们的琐碎替换意味着我们建议cupy
该“设备”内存与所有其他普通的设备内存一样,具有特定的设备关联。在您这样的单个设备设置中,这种区别是没有意义的。但是,这不适用于固定内存的强大多设备使用。为此,再次建议cupy
是通过提出问题来对进行更有效的更改。
这是一个例子:
import os import numpy as np import cupy class PMemory(cupy.cuda.memory.BaseMemory): def __init__(self, size): self.size = size self.device_id = cupy.cuda.device.get_device_id() self.ptr = 0 if size > 0: self.ptr = cupy.cuda.runtime.hostAlloc(size, 0) def __del__(self): if self.ptr: cupy.cuda.runtime.freeHost(self.ptr) def my_pinned_allocator(bsize): return cupy.cuda.memory.MemoryPointer(PMemory(bsize),0) cupy.cuda.set_allocator(my_pinned_allocator) #Create 4 .npy files, ~4GB each for i in range(4): print(i) numpyMemmap = np.memmap( 'reg.memmap'+str(i), dtype='float32', mode='w+', shape=( 10000000 , 100)) 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): print(i) NPYmemmap.append( np.load( 'reg.memmap'+str(i)+'.npy' , mmap_mode = 'r+' ) ) del NPYmemmap # allocate pinned memory storage CPYmemmap = [] for i in range(4): print(i) CPYmemmap.append( cupy.load( 'reg.memmap'+str(i)+'.npy' , mmap_mode = 'r+' ) ) cupy.cuda.set_allocator(None)
我没有在具有这些文件大小的25GB主机内存的安装程序中对此进行测试。但是我已经用超过我GPU的设备内存的其他文件大小对其进行了测试,并且它似乎可以工作。
同样,未经彻底测试的实验性代码可能会有所不同,因此最好通过提交大量的github问题来实现此功能。而且,正如我之前提到的,从设备代码访问这种“设备内存”通常比普通cupy
设备内存要慢得多。
最后,这并不是真正的“内存映射文件”,因为所有文件内容都将被加载到主机内存中,此外,这种方法“用完”主机内存。如果要访问20GB的文件,则将需要超过20GB的主机内存。只要“加载”了这些文件,就会使用20GB的主机内存。
在我看来,当前cupy
没有提供固定的分配器来代替普通的设备内存分配器,即可以用作固定的分配器cupy.ndarray
。如果这对您很重要,那么您可以考虑提出一个冒号的问题。
但是,似乎可以创建一个。这应视为实验代码。并且有一些与其使用相关的问题。
基本思想是,我们将使用cupy.cuda.set_allocator
已经建议的方式,用我们自己的来替换cupy的默认设备内存分配器。我们需要提供自己的替代品,以BaseMemory
用作的存储库cupy.cuda.memory.MemoryPointer
。此处的主要区别在于,我们将使用固定的内存分配器而不是设备分配器。这是PMemory
以下课程的要点。
需要注意的其他事项:
在使用固定的内存(分配)完成所需的操作之后,您可能应该将cupy
分配器恢复为其默认值。不幸的是,与不同cupy.cuda.set_allocator
,我没有找到对应的cupy.cuda.get_allocator
,这使我感到不足cupy
,这似乎也值得向我提出杯状问题。但是,对于本演示,我们将仅返回到None
使用默认设备内存分配器之一的选择(但是不使用池分配器)。
通过提供这种最小的固定内存分配器,我们仍然建议cupy这是普通的设备内存。这意味着不能直接从宿主代码访问它(实际上,但是cupy不知道)。因此,各种操作(例如cupy.load
)将创建不需要的主机分配和不需要的复制操作。我认为解决这个问题将需要的不仅是我建议的小改变。但至少对于您的测试用例,此额外开销可能是可管理的。看来您想一次从磁盘加载数据,然后将其保留在那里。对于这种类型的活动,这应该是可管理的,尤其是因为您将其分为多个部分。就像我们将看到的那样,对于25GB的主机内存来说,处理四个5GB的块实在太多了。我们将需要为四个5GB块(实际上是固定的)分配主机内存,并且还需要一个额外的5GB“开销”缓冲区的额外空间。因此25GB不足以实现这一目标。但是出于演示目的,
与cupy的默认设备内存分配器关联的普通设备内存与特定设备有关联。固定的内存不必具有这样的关联,但是BaseMemory
用类似的类对我们的琐碎替换意味着我们建议cupy
该“设备”内存与所有其他普通的设备内存一样,具有特定的设备关联。在您这样的单个设备设置中,这种区别是没有意义的。但是,这不适用于固定内存的强大多设备使用。为此,再次建议cupy
是通过提出问题来对进行更有效的更改。
这是一个例子:
import os import numpy as np import cupy class PMemory(cupy.cuda.memory.BaseMemory): def __init__(self, size): self.size = size self.device_id = cupy.cuda.device.get_device_id() self.ptr = 0 if size > 0: self.ptr = cupy.cuda.runtime.hostAlloc(size, 0) def __del__(self): if self.ptr: cupy.cuda.runtime.freeHost(self.ptr) def my_pinned_allocator(bsize): return cupy.cuda.memory.MemoryPointer(PMemory(bsize),0) cupy.cuda.set_allocator(my_pinned_allocator) #Create 4 .npy files, ~4GB each for i in range(4): print(i) numpyMemmap = np.memmap( 'reg.memmap'+str(i), dtype='float32', mode='w+', shape=( 10000000 , 100)) 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): print(i) NPYmemmap.append( np.load( 'reg.memmap'+str(i)+'.npy' , mmap_mode = 'r+' ) ) del NPYmemmap # allocate pinned memory storage CPYmemmap = [] for i in range(4): print(i) CPYmemmap.append( cupy.load( 'reg.memmap'+str(i)+'.npy' , mmap_mode = 'r+' ) ) cupy.cuda.set_allocator(None)
我没有在具有这些文件大小的25GB主机内存的安装程序中对此进行测试。但是我已经用超过我GPU的设备内存的其他文件大小对其进行了测试,并且它似乎可以工作。
同样,未经彻底测试的实验性代码可能会有所不同,因此最好通过提交大量的github问题来实现此功能。而且,正如我之前提到的,从设备代码访问这种“设备内存”通常比普通cupy
设备内存要慢得多。
最后,这并不是真正的“内存映射文件”,因为所有文件内容都将被加载到主机内存中,此外,这种方法“用完”主机内存。如果要访问20GB的文件,则将需要超过20GB的主机内存。只要“加载”了这些文件,就会使用20GB的主机内存。