将随机值复制到 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)

现在可以在设备上正确读取值。