pyopencl 初始化非零 float4 数组

pyopencl initialize non zero float4 array

我想用 float4 类型填充一个数组。我不知道如何用零以外的东西初始化数组。我试过这个的变体,但这是我带来的,它解释了我想做的事情:

import pyopencl as cl
import numpy as np

kernelSource = """
__kernel void addOneToFloat4(__global float4 *a)
{
    int gid = get_global_id(0);
        a[gid] += 1.0f;
}
"""

context = cl.create_some_context()
queue = cl.CommandQueue(context)
device = context.devices[0]
program = cl.Program(context, kernelSource).build()

N = 10
HOST_array = np.array([[1, 0, 0, 0]]*N, dtype=cl.cltypes.float4)
TARGET_array = cl.Buffer(context, cl.mem_flags.READ_WRITE | cl.mem_flags.COPY_HOST_PTR, hostbuf=HOST_array)
cl.enqueue_copy(queue, dest=TARGET_array, src=HOST_array)

program.addOneToFloat4(queue, (N,), None, TARGET_array)

cl.enqueue_copy(queue, dest=HOST_array, src=TARGET_array)
queue.finish()

print(HOST_array)

当然不行,因为它理解spahe(N, 4)的输入,但由于float4只是一个类型,所以它需要(N, )大小。

我见过有人用 np.zeros(N, dtype=float4) 初始化,但我不想初始化为 0。

我发现 pyopencl 的实际例子很少,而且 documentation 并不总是有帮助,它甚至没有提到 float3float4

如果我们查看 OpenCL documentation,我们可以看到类型 float4 是一个结构,其字段为 .x, .y, .z, .w。它也被声明为一种类型,所以我希望能够像使用任何其他类型一样使用它。

没有 cl 东西,这里是创建数组的示例

In [50]: myStruct = np.dtype(
    ...:         [("position", float),
    ...:          ("direction", float),
    ...:          ("er", float),
    ...:          ("weight", float)])

In [55]: arr = np.zeros(5,myStruct)
In [56]: arr
Out[56]: 
array([(0., 0., 0., 0.), (0., 0., 0., 0.), (0., 0., 0., 0.),
       (0., 0., 0., 0.), (0., 0., 0., 0.)],
      dtype=[('position', '<f8'), ('direction', '<f8'), ('er', '<f8'), ('weight', '<f8')])
In [57]: arr['position']
Out[57]: array([0., 0., 0., 0., 0.])
In [58]: arr['position']=np.arange(5)
In [59]: arr['direction']=3
In [60]: arr['er']=np.array([[1,2,3,4,5]])
In [61]: arr['weight']=np.array([[1,2,3,4,5]]).T
Traceback (most recent call last):
  Input In [61] in <cell line: 1>
    arr['weight']=np.array([[1,2,3,4,5]]).T
ValueError: could not broadcast input array from shape (5,1) into shape (5,)

查了下pyopencl的源码,发现问题出在运行时生成的函数上。此外,文档中并未明确说明这些功能是否可用。因此,要将数组加载到 type<n> 中,您需要调用函数 cl.cltypes.make_type<n> 并将类型设置为 cl.cltypes.type<n>。因为这是在运行时生成的,所以它不会在命名空间中,因此您的 ide 将无法识别它们。

myFloat4 = cl.cltypes.make_float4(0,1,1,0)
myArrayFloat4 = np.array([myFloat4], dtype=cl.cltypes.float4)

因此,为了完整起见,这是我的解决方法:

import pyopencl as cl
import numpy as np

kernelSource = """
__kernel void addOneToFloat4(__global float4 *a)
{
    int gid = get_global_id(0);
        a[gid] += 1.0f;
}
"""

context = cl.create_some_context()
queue = cl.CommandQueue(context)
device = context.devices[0]
program = cl.Program(context, kernelSource).build()

N = 10
HOST_array = np.array([cl.cltypes.make_float4(1, 0, 0, 0)]*N, dtype=cl.cltypes.float4)
TARGET_array = cl.Buffer(context, cl.mem_flags.READ_WRITE | cl.mem_flags.COPY_HOST_PTR, hostbuf=HOST_array)
cl.enqueue_copy(queue, dest=TARGET_array, src=HOST_array)

program.addOneToFloat4(queue, (N,), None, TARGET_array)

cl.enqueue_copy(queue, dest=HOST_array, src=TARGET_array)
queue.finish()

print(HOST_array)