在python中如何将标量参数传递给OpenCL内核?

时间:2016-04-19 17:10:00

标签: python opencl pyopencl

我正在使用OpenCL的python绑定,我编写了一个期望标量(浮点)参数的内核,但我无法找到传递它的正确方法。

如果我只是调用

prg.bloop(queue, [width,height], None, centers_g, 16/9, result_g)

我收到此错误:

pyopencl.cffi_cl.LogicError: when processing argument #2 (1-based): 'float' does not support the buffer interface

如果我用numpy.float32(16/9)包装它,那么内核就像传递0而不是1.7777777一样。

以下是更多源代码,以帮助您了解我正在做的事情。

def mission2(cells, width, height):
    ctx = cl.create_some_context()
    queue = cl.CommandQueue(ctx)

    centers = numpy.array(list(cells), dtype=numpy.float32)

    centers_g = cl.Buffer(ctx, cl.mem_flags.READ_ONLY|cl.mem_flags.COPY_HOST_PTR, hostbuf = centers)

    prg = cl.Program(ctx, """
__kernel void test1(__global char *out) {
    out[0] = 77;
}

float sphere(float r, float x, float y)
{
    float q = r*r-(x*x+y*y);
    if (q<0)
        return 0;
    return sqrt(q);
}

__kernel void bloop(__global const float centers[][6], float aspect, __global char * out)
{
    int u = get_global_id(0);
    int v = get_global_id(1);
    int width = get_global_size(0);
    int height = get_global_size(1);

    float x = u/(float)width * aspect;
    float y = v/(float)height;

    float max = sphere(0.3, x-centers[0][0], y-centers[0][1]);

    int idx = u+v*width;
    out[idx] = 255*max;

}

    """).build()

    result_g = cl.Buffer(ctx, cl.mem_flags.WRITE_ONLY, width*height)


    if False:
        prg.test1(queue, [width,height], None, result_g)
    else:
        prg.bloop(queue, [width,height], None, centers_g, numpy.float32(16/9), result_g)


    result = numpy.zeros([height,width], dtype=numpy.uint8)
    future = cl.enqueue_copy(queue, result, result_g)
    future.wait()

    print(result)

    imsave("/tmp/bloop.png", result, cmap = matplotlib.pyplot.get_cmap('gray'))

1 个答案:

答案 0 :(得分:1)

为了将标量传递给OpenCL内核,您可以使用set_scalar_arg_dtypes函数,如下所示:

kernel = prg.bloop
kernel.set_scalar_arg_dtypes( [None, numpy.float32, None] )
kernel(queue, [width, height], None, centers_g, aspect, result_g)

The manual page明确指出,如果你这样编码就行不了:

prg.bloop.set_scalar_arg_dtypes( [None, numpy.float32, None] )
# this will fail:
prg.bloop(queue, [width, height], None, centers_g, 16/9, result_g)

因为&#34;此rountine设置的信息附加到单个内核实例。每次使用program.kernel属性访问时都会创建一个新的内核实例。&#34;