【问题标题】:Pass vector (float4) kernell argument to OpenCL (Python)将向量 (float4) kernell 参数传递给 OpenCL (Python)
【发布时间】:2013-01-18 23:48:30
【问题描述】:

是否有任何简单的方法可以将 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 快(因为它可以被所有工作项共享为常量)

【问题讨论】:

  • 您将 myFloat4 定义为一个 numpy 数组。如果将其视为实际数组,则不能将其作为 float4 之类的参数传递,因为它实际上是 float vec[4]。在 C/C++ 中,您可以将其转换为 float4,但我不知道它在 Python 中是如何工作的。

标签: python numpy parameter-passing opencl pyopencl


【解决方案1】:

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

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

希望这对有同样疑问的人有所帮助。

【讨论】:

  • 我自己还在想办法,但是对于 floatN 数组,第二个参数应该是 N,还是 /last/ 参数应该是 N? np.random.rand(SIZEx,SIZEy,4) 似乎在 np.random.rand(SIZEx,4,SIZEy) 不起作用的地方工作。
【解决方案2】:

我不知道 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);

希望对您有所帮助。 埃里克。

【讨论】:

    【解决方案3】:

    问题来了:

    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 )
    

    剩下的代码没问题

    【讨论】:

      【解决方案4】:

      我发现这是在 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
      

      【讨论】:

      • 如何将包含 float4 的 numpy 数组转换为 numpy.float32
      【解决方案5】:

      我注意到三件事:

      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)
        

      【讨论】:

        猜你喜欢
        • 2012-10-18
        • 2016-08-12
        • 2015-07-21
        • 2016-07-24
        • 1970-01-01
        • 2020-08-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多