将vector(float4)kernell参数传递给OpenCL(Python)

时间:2013-02-04 09:43:58

标签: python numpy parameter-passing opencl pyopencl

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

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

例如: 的 kernnel:

__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快(因为它可以被所有工作项共享为常量)

5 个答案:

答案 0 :(得分:2)

我觉得这是在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

答案 1 :(得分: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 )

剩下的代码很好

答案 2 :(得分: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)
    

答案 3 :(得分:0)

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

我参与数组的方式:np.zeros((SIZE,4), dtype=np.float32)

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

答案 4 :(得分:0)

我不知道Python中的OpenCl,但我确实将doubleintdouble8或任何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);

希望它有所帮助。 埃里克。