有没有办法解决 PyOpenCL 中的限制,即:
array.data
失败了
pyopencl.array.ArrayHasOffsetError:您尝试的操作尚不支持从缓冲区开头偏移的数组。
我试过了:
a.base_data[a.offset: a.offset + a.nbytes]
这似乎有时有效,但其他时候我得到:
pyopencl.LogicError:clCreateSubBuffer 失败:值无效
clcreateSubBuffer
需要具有origin
对齐的偏移量(或者在这种情况下称为 ),并且size
+origin
必须在缓冲区的范围内。
如果 (origin, size) 指定的区域超出缓冲区的范围,则在 errcode_ret 中返回 CL_INVALID_VALUE。
如果上下文中没有与原始值与 CL_DEVICE_MEM_BASE_ADDR_ALIGN 值对齐的缓冲区关联的设备,则在 errcode_ret 中返回 CL_MISALIGNED_SUB_BUFFER_OFFSET。
对于您看到的特定错误,您的程序或 pyopencl 错误地计算了偏移后数组的大小。即使您解决了这个问题,如果原始偏移量未与CL_DEVICE_MEM_BASE_ADDR_ALIGN
.
话虽如此,NVIDIA 似乎打破了规范并允许任意偏移。因此,您的里程可能会因硬件而异。
如果您只是想获得一个标记数组数据开始的缓冲区,以传递给内核,则不必担心大小。这是一个获取指向偏移数据开始的大小为 1 的缓冲区的函数:
def data_ptr(array):
if array.offset:
return array.base_data.get_sub_region(array.offset, 1)
else:
return array.data
如果您需要一个指向偏移数据开头的指针,您可以使用它来传递给内核。clV
这是一个示例,我想将数组的一个子区域设置clA
为值 3。我data_ptr
用来获取指向clV
数据开头的指针。
import numpy as np
import pyopencl as cl
import pyopencl.array
ctx = cl.create_some_context()
queue = cl.CommandQueue(ctx)
m, n = 5, 5
A = np.random.uniform(size=(m, n)).astype(np.float32)
clA = cl.array.Array(queue, A.shape, A.dtype)
clA.set(A)
clV = clA[1::2, 1::2]
def data(array):
if array.offset:
return array.base_data.get_sub_region(array.offset, 1)
else:
return array.data
source = """
__kernel void fn(long si, long sj, __global float *Y)
{
const int i = get_global_id(0);
const int j = get_global_id(1);
Y[i*si + j*sj] = 3;
}
"""
kernel = cl.Program(ctx, source).build().fn
gsize = clV.shape
lsize = None
estrides = np.array(clV.strides) / clV.dtype.itemsize
kernel(queue, gsize, lsize, estrides[0], estrides[1], data_ptr(clV))
print(clA.get())