将随机值复制到 OpenCL 设备 returns 无效值
Copying random values to OpenCL device returns non valid values
我有一个简单的问题,我想在 OpenCL 设备上复制随机生成的浮点数并在设备上使用这些值,因为 OpenCL
不提供随机数生成器。
但是,在设备上似乎无法正确使用这些值。返回给 HOST_result
的值不是最初生成的值,它们可能只是内存中较旧的值 space.
这是一个最低限度的非工作示例。我会要求有人指出这段代码有什么问题。
import pyopencl as cl
import numpy as np
kernelSource = """
__kernel void testKernel(__global float *result, __global float *randomNum)
{
int gid = get_global_id(0);
result[gid] = randomNum[gid];
}
"""
context = cl.create_some_context()
queue = cl.CommandQueue(context)
device = context.devices[0]
program = cl.Program(context, kernelSource).build()
N = 4
HOST_result = np.ones(N, dtype=cl.cltypes.float)
print(HOST_result.shape)
DEVICE_result = cl.Buffer(context, cl.mem_flags.READ_WRITE | cl.mem_flags.COPY_HOST_PTR, hostbuf=HOST_result)
HOST_rand = np.random.uniform(low=0.0, high=1.0, size=N)
print(HOST_rand.shape)
HOST_rand.astype(cl.cltypes.float)
DEVICE_rand = cl.Buffer(context, cl.mem_flags.READ_ONLY | cl.mem_flags.COPY_HOST_PTR, hostbuf=HOST_rand)
program.testKernel(queue, HOST_result.shape, None, DEVICE_result, DEVICE_rand)
queue.finish()
cl.enqueue_copy(queue, dest=HOST_result, src=DEVICE_result)
print(HOST_rand)
print(HOST_result)
"""
Using cl.Buffer() with the COPY_HOST_PTR flag, the host buffer is copied to the device buffer and it allocates memory
the size of the buffer where HOST_PTR points to.
"""
输出是
(4,)
(4,)
[0.02692256 0.82201746 0.05025519 0.31266968]
[-6.9784595e-12 1.2153804e+00 -2.4271645e-30 1.8305043e+00]
如果我们将 HOST_rand
更改为 HOST_rand = np.zeros(N, dtype=cl.cltypes.float)
,则不会发生此错误。最后的所有值都按预期变为 [0, 0, 0, 0]
。任何 np.array([])
似乎也有效。
事实证明,HOST_rand.astype(cl.cltypes.float)
改变了类型,但没有改变内存对齐方式。
因此,因为我的函数使用 float32
,所以在 OpenCL
设备上读取的值是错误的。
要补救这种情况,可以使用 numpy
generator objects。该对象允许为随机值生成传递更多参数。
我们得到默认的 Generator
,然后我们传递正确的类型。
rndGenerator = np.random.default_rng()
HOST_rand = rndGenerator.random(size=N, dtype=cl.cltypes.float)
现在可以在设备上正确读取值。
我有一个简单的问题,我想在 OpenCL 设备上复制随机生成的浮点数并在设备上使用这些值,因为 OpenCL
不提供随机数生成器。
但是,在设备上似乎无法正确使用这些值。返回给 HOST_result
的值不是最初生成的值,它们可能只是内存中较旧的值 space.
这是一个最低限度的非工作示例。我会要求有人指出这段代码有什么问题。
import pyopencl as cl
import numpy as np
kernelSource = """
__kernel void testKernel(__global float *result, __global float *randomNum)
{
int gid = get_global_id(0);
result[gid] = randomNum[gid];
}
"""
context = cl.create_some_context()
queue = cl.CommandQueue(context)
device = context.devices[0]
program = cl.Program(context, kernelSource).build()
N = 4
HOST_result = np.ones(N, dtype=cl.cltypes.float)
print(HOST_result.shape)
DEVICE_result = cl.Buffer(context, cl.mem_flags.READ_WRITE | cl.mem_flags.COPY_HOST_PTR, hostbuf=HOST_result)
HOST_rand = np.random.uniform(low=0.0, high=1.0, size=N)
print(HOST_rand.shape)
HOST_rand.astype(cl.cltypes.float)
DEVICE_rand = cl.Buffer(context, cl.mem_flags.READ_ONLY | cl.mem_flags.COPY_HOST_PTR, hostbuf=HOST_rand)
program.testKernel(queue, HOST_result.shape, None, DEVICE_result, DEVICE_rand)
queue.finish()
cl.enqueue_copy(queue, dest=HOST_result, src=DEVICE_result)
print(HOST_rand)
print(HOST_result)
"""
Using cl.Buffer() with the COPY_HOST_PTR flag, the host buffer is copied to the device buffer and it allocates memory
the size of the buffer where HOST_PTR points to.
"""
输出是
(4,)
(4,)
[0.02692256 0.82201746 0.05025519 0.31266968]
[-6.9784595e-12 1.2153804e+00 -2.4271645e-30 1.8305043e+00]
如果我们将 HOST_rand
更改为 HOST_rand = np.zeros(N, dtype=cl.cltypes.float)
,则不会发生此错误。最后的所有值都按预期变为 [0, 0, 0, 0]
。任何 np.array([])
似乎也有效。
事实证明,HOST_rand.astype(cl.cltypes.float)
改变了类型,但没有改变内存对齐方式。
因此,因为我的函数使用 float32
,所以在 OpenCL
设备上读取的值是错误的。
要补救这种情况,可以使用 numpy
generator objects。该对象允许为随机值生成传递更多参数。
我们得到默认的 Generator
,然后我们传递正确的类型。
rndGenerator = np.random.default_rng()
HOST_rand = rndGenerator.random(size=N, dtype=cl.cltypes.float)
现在可以在设备上正确读取值。