2013-07-13 3 views
1

как передать некоторые параметры, которые будут обрабатываться в .cl файле в качестве препроцессора, определить с помощью pyopencl?Как передать параметры в ядро ​​ocl с помощью pyopencl?

Значение:

foo.cl

# define LIMIT 12 
typedef struct { 
    uint i[LIMIT]; 
} foomatic; 

превращается в

foo_nodefs.cl

typedef struct { 
    uint i[LIMIT]; // python script passing LIMIT to set it 
} foomatic; 

Спасибо,

John

ответ

3

Редактировать: продлить ответ, сделав его максимально подробным.

Есть два способа сделать это:

  1. (метапрограммирования) Добавить свои директивы препроцессора непосредственно в строку с исходным кодом, или даже запустить свой собственный препроцессор с помощью некоторых шаблонизатор.

    import pyopencl as cl 
    import numpy 
    import numpy.linalg as la 
    
    a = numpy.random.rand(50000).astype(numpy.float32) 
    b = numpy.random.rand(50000).astype(numpy.float32) 
    
    ctx = cl.create_some_context() 
    queue = cl.CommandQueue(ctx) 
    
    mf = cl.mem_flags 
    a_buf = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=a) 
    b_buf = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=b) 
    dest_buf = cl.Buffer(ctx, mf.WRITE_ONLY, b.nbytes) 
    
    defines = """ 
        #define AXIS 0 
        #define COEFF 1 
        """ 
    
    prg = cl.Program(ctx, 
        defines + 
        """ 
        __kernel void sum(__global const float *a, 
        __global const float *b, __global float *c) 
        { 
         int gid = get_global_id(AXIS); 
         c[gid] = a[gid] + b[gid] + COEFF; 
        } 
        """).build() 
    
    prg.sum(queue, a.shape, None, a_buf, b_buf, dest_buf) 
    
    a_plus_b = numpy.empty_like(a) 
    cl.enqueue_copy(queue, a_plus_b, dest_buf) 
    
    print(la.norm(a_plus_b - (a+b+1)), la.norm(a_plus_b)) 
    
  2. (C-полосная) использовать options ключевое слово Program.build передать параметры сборки непосредственно clBuildProgram():

    import pyopencl as cl 
    import numpy 
    import numpy.linalg as la 
    
    a = numpy.random.rand(50000).astype(numpy.float32) 
    b = numpy.random.rand(50000).astype(numpy.float32) 
    
    ctx = cl.create_some_context() 
    queue = cl.CommandQueue(ctx) 
    
    mf = cl.mem_flags 
    a_buf = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=a) 
    b_buf = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=b) 
    dest_buf = cl.Buffer(ctx, mf.WRITE_ONLY, b.nbytes) 
    
    prg = cl.Program(ctx, """ 
        __kernel void sum(__global const float *a, 
        __global const float *b, __global float *c) 
        { 
         int gid = get_global_id(AXIS); 
         c[gid] = a[gid] + b[gid] + COEFF; 
        } 
        """).build(options=['-D', 'AXIS=0', '-D', 'COEFF=1']) 
    
    prg.sum(queue, a.shape, None, a_buf, b_buf, dest_buf) 
    
    a_plus_b = numpy.empty_like(a) 
    cl.enqueue_copy(queue, a_plus_b, dest_buf) 
    
    print(la.norm(a_plus_b - (a+b+1)), la.norm(a_plus_b)) 
    

(я использовал доработанный исходный код главной страницы PyOpenCL docs. Проверено на pyopencl 2013.1).

+0

Хорошо, но как именно я это делаю? –

+0

Вы спрашиваете, как объединить две строки в Python? Пожалуйста, предоставьте мне некоторый минимальный пример для работы, потому что я не уверен, что понимаю этот вопрос. – fjarri

+0

Нет. Я хотел бы знать, где вы хотите, чтобы я поместил параметр в виде строки? Вы имеете в виду строку, которую вы читаете, чтобы загрузить источник cl для ее создания? Значение cl.Program (ctx, ) .build() –