1

有没有简单的方法可以将 float4 或任何其他向量参数传递给 OpenCL 内核?对于标量参数(int,float),您可以在调用内核时直接传递它。对于数组参数,您必须先使用 cl.Buffer() 将其复制到 GPU,然后再传递指针。当然有可能以与数组相同的方式传递 float4。但我问是否有任何更简单,更清晰的方法。(尤其是使用 Python、numpy、pyOpenCL)

我尝试将大小为 4*float32 的 numpy 数组作为 float4 传递,但它不起作用。是否有可能以其他方式做到这一点?

例如: 内核:

__kernel void myKernel( __global float  * myArray, float myFloat, float4 myFloat4 )

Python:

myFloat4   = numpy.array  ( [1.0 ,2.0 ,3.0], dtype=np.float32 ) 
myArray    = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=myArray_host)
kernelargs = ( myArray , numpy.float32(myFloat) , myFloat4) 
prg.myKernel(queue, cl_myArray.shape() , None, *(kernelargs) )

我得到错误:

pyopencl.LogicError: when processing argument #2 (1-based): clSetKernelArg failed: invalid arg size

另一种可能性是将它作为标量 int 或 float 的集合传递 - 例如:

__kernel void myKernel( __global float  * myArray, float myFloat, float myFloat4_x, float myFloat4_y, float myFloat4_z  )

kernelargs = ( myArray , numpy.float32(myFloat) ,numpy.float32(myFloat4_x),numpy.float32(myFloat4_y),numpy.float32(myFloat4_z))

但这也不是很方便——如果你想将 4x float4 和 5x int3 传递给 kernell,你很容易迷失在许多变量名中。

我认为传递 int 和 float 的向量 (2,3,4) 在 OpenCL 中一定很常见 - 例如 3D 数据网格的大小。所以我想知道是否真的有必要使用 cl.Buffer() 作为指针来传递它。

我猜常量参数 float4 也比 *float 快(因为它可以被所有工作项共享为常量)

4

5 回答 5

3

我发现这是在 python 中创建 float4 的好方法:

import numpy as np
import pyopencl as cl
import pyopencl.array as cl_array

data= np.zeros(N, dtype=cl_array.vec.float4)

编辑:还要给出 MWE:

import numpy as np
import pyopencl as cl
import pyopencl.array as cl_array


deviceID = 0
platformID = 0
workGroup=(1,1)

N = 10
testData = np.zeros(N, dtype=cl_array.vec.float4)

dev = cl.get_platforms()[platformID].get_devices()[deviceID]

ctx = cl.Context([dev])
queue = cl.CommandQueue(ctx)
mf = cl.mem_flags
Data_In = cl.Buffer(ctx, mf.READ_WRITE, testData.nbytes)


prg = cl.Program(ctx, """

__kernel void   Pack_Cmplx( __global float4* Data_In, int  N)
{
  int gid = get_global_id(0);

  Data_In[gid] = 1;
}
 """).build()

prg.Pack_Cmplx(queue, (N,1), workGroup, Data_In, np.int32(N))
cl.enqueue_copy(queue, testData, Data_In)


print testData
于 2014-05-04T22:31:44.073 回答
1

问题在这里:

myFloat4   = numpy.array  ( [1.0 ,2.0 ,3.0], dtype=numpy.float32 )

但 myFloat4.size 等于 3

只需输入:

myFloat4   = numpy.array  ( [1.0 ,2.0 ,3.0, 4.0], dtype=numpy.float32 )

其余代码没问题

于 2014-01-20T15:04:27.043 回答
1

我注意到三件事:

  1. 查看错误消息,第二个内核参数似乎存在问题,即myFloat. 如果你const在内核签名中声明它是一个参数会发生什么?如果你这样做会发生什么

    myFloat = myFloat.astype(np.float32)
    kernelArgs = (..., myFloat, ...)
    prg.myKernel(...)
    
  2. 您想定义一个四元素向量myFloat4,但[1.0, 2.0, 3.0]只给出三个值。还可以尝试const float4 myFloat4在内核签名中进行设置。

  3. kernelargs在实际内核调用中,元组不需要额外的括号:

    prg.myKernel(queue, cl_myArray.shape() , None, *kernelargs)
    
于 2017-03-21T15:02:47.463 回答
0

对我来说,当我运行 opencl 内核时,创建一个形状为 (SIZE,4) 和 dtype float32 的 numpy 数组效果很好。确保第二维与您想要的 floatN 匹配,如果它们不匹配,它不会抛出任何错误,但在我的情况下,它会导致显卡驱动程序崩溃。

我初始化数组的方式:np.zeros((SIZE,4), dtype=np.float32)

希望这可以帮助任何想知道的人。

于 2013-08-23T09:52:28.767 回答
0

我不知道 Python 中的 OpenCl,但我确实将double, int,double8或任何 OpenCl 类型传递给内核。
假设 N 是整数,alpha 是 double,vect 是 double8。
我所做的是

clSetKernelArg(kernel, 0, sizeof(int),  &N);
clSetKernelArg(kernel, 18, sizeof(double), &alpha);
clSetKernelArg(kernel, 11, sizeof(cl_double8), &vect);

希望能帮助到你。埃里克。

于 2013-10-08T23:48:45.343 回答