2016-04-19 16 views
0

ich die Python-Bindings für OpenCL verwende, und ich habe einen Kernel geschrieben, die einen skalaren (float) Argument erwartet, aber ich kann die richtige Art und Weise nicht herausfinden, es zu passieren in.Wie übergebe ich in Python ein skalares Argument an einen OpenCL-Kernel?

Wenn ich einfach

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

ich diesen Fehler:

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

wenn ich es mit numpy.float32(16/9) wickeln dann der Kernel verhält, als ob es 0 statt 1,7777777 geben wurden.

Hier ist mehr von dem Quellcode für den Fall, dass Sie verstehen, was ich mache.

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')) 
+0

Sind Sie sicher, dass es sich nicht so verhält, als wäre es 1? 16/9 gibt 1 in Python 2. Wrapping in numpy.float32 ist was ich mache, wenn ich PyOpenCL benutze und es funktioniert hier. –

+0

Center ist nicht in Ihrem Kernel definiert. Es ist in Ihrem Host-Code definiert. Der Fehler sagt es: Buffer-Schnittstelle ist nicht für Floats definiert. "Zentren" ist ein Float. Also Zentren [] [6] ist illegal. – Dschoni

+0

Ich benutze nicht Python 2. Dies ist eine Python 3 App und wenn ich 'print (16/9)' es gibt mir definitiv 1.77777. –

Antwort

1

Um Skalare zu einem OpenCL Kernel übergeben Sie die set_scalar_arg_dtypes funktionieren wie diese verwenden:

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 eindeutig fest, dass es nicht funktioniert, wenn Sie es wie folgt Code:

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) 

weil "Die von dieser Rountine gesetzten Informationen sind an eine einzige Kernel-Instanz gebunden. Eine neue Kernel-Instanz wird jedes Mal erstellt, wenn Sie das Programm.Kernel-Attribut ac verwenden cess. "