gpt4 book ai didi

python - 如何从 gpu 内存地址创建 PyCUDA GPUArray?

转载 作者:太空宇宙 更新时间:2023-11-03 14:43:27 25 4
gpt4 key购买 nike

我正在使用 PyTorch,并希望在 PyCUDA 的帮助下对张量数据进行一些算术运算。我可以通过 t.data_ptr() 获取 cuda 张量 t 的内存地址。我能否以某种方式使用此地址以及我对大小和数据类型的了解来初始化 GPUArray?我希望避免复制数据,但这也是一种替代方法。

最佳答案

事实证明这是可能的。我们需要一个指针来处理数据,这需要一些额外的功能:

class Holder(PointerHolderBase):

def __init__(self, tensor):
super().__init__()
self.tensor = tensor
self.gpudata = tensor.data_ptr()

def get_pointer(self):
return self.tensor.data_ptr()

def __int__(self):
return self.__index__()

# without an __index__ method, arithmetic calls to the GPUArray backed by this pointer fail
# not sure why, this needs to return some integer, apparently
def __index__(self):
return self.gpudata

然后我们可以使用此类来实例化 GPUArray。该代码使用 Reikna 数组,它是一个子类,但也应该与 pycuda 数组一起使用。

def tensor_to_gpuarray(tensor, context=pycuda.autoinit.context):
'''Convert a :class:`torch.Tensor` to a :class:`pycuda.gpuarray.GPUArray`. The underlying
storage will be shared, so that modifications to the array will reflect in the tensor object.
Parameters
----------
tensor : torch.Tensor
Returns
-------
pycuda.gpuarray.GPUArray
Raises
------
ValueError
If the ``tensor`` does not live on the gpu
'''
if not tensor.is_cuda:
raise ValueError('Cannot convert CPU tensor to GPUArray (call `cuda()` on it)')
else:
thread = cuda.cuda_api().Thread(context)
return reikna.cluda.cuda.Array(thread, tensor.shape, dtype=torch_dtype_to_numpy(tensor.dtype), base_data=Holder(tensor))

我们可以返回此代码。我还没有找到一种不复制数据就可以做到这一点的方法。

def gpuarray_to_tensor(gpuarray, context=pycuda.autoinit.context):
'''Convert a :class:`pycuda.gpuarray.GPUArray` to a :class:`torch.Tensor`. The underlying
storage will NOT be shared, since a new copy must be allocated.
Parameters
----------
gpuarray : pycuda.gpuarray.GPUArray
Returns
-------
torch.Tensor
'''
shape = gpuarray.shape
dtype = gpuarray.dtype
out_dtype = numpy_dtype_to_torch(dtype)
out = torch.zeros(shape, dtype=out_dtype).cuda()
gpuarray_copy = tensor_to_gpuarray(out, context=context)
byte_size = gpuarray.itemsize * gpuarray.size
pycuda.driver.memcpy_dtod(gpuarray_copy.gpudata, gpuarray.gpudata, byte_size)
return out

旧答案

from pycuda.gpuarray import GPUArray


def torch_dtype_to_numpy(dtype):
dtype_name = str(dtype)[6:] # remove 'torch.'
return getattr(np, dtype_name)


def tensor_to_gpuarray(tensor):
if not tensor.is_cuda:
raise ValueError('Cannot convert CPU tensor to GPUArray (call `cuda()` on it)')
else:
array = GPUArray(tensor.shape, dtype=torch_dtype_to_numpy(tensor.dtype),
gpudata=tensor.data_ptr())
return array.copy()

不幸的是,传递一个 int 作为 gpudata 关键字(或 pytorch 论坛中建议的 pycuda.driver.PointerHolderBase 的子类型)似乎在表面上有效,但许多操作因看似无关的错误而失败。复制数组似乎将其转换为可用格式。我认为这与 gpudata 成员应该是一个 pycuda.driver.DeviceAllocation 对象有关,它似乎无法从 Python 实例化。

现在如何从原始数据返回到 Tensor 是另一回事。

关于python - 如何从 gpu 内存地址创建 PyCUDA GPUArray?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51438232/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com