2013-04-11 9 views
5

Следующий код python использует PyOpenCL для заполнения массива a_plus_b с суммой элементов в массиве b (это не моя фактическая цель, но это самый простой код, который я могу найти, который все еще показывает проблему). неПочему этот код opencl не детерминирован?

import pyopencl as cl 
import numpy as np 
import numpy.linalg as la 

height = 50 
width = 32 

b = np.arange(width,dtype=np.int32) 

ctx = cl.create_some_context() 
queue = cl.CommandQueue(ctx) 

mf = cl.mem_flags 
b_buf = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=b) 
dest_buf = cl.Buffer(ctx, mf.WRITE_ONLY, height*4) 

prg = cl.Program(ctx, """ 
    __kernel void sum(__global const int *b, __global int *c) 
    { 
     int x = get_global_id(1); 
     int y; 
     c[x] = 0; 
     for(y=0;y<get_global_size(0);y++) { 
      c[x] += b[y]; 
     } 
    } 
    """).build() 

prg.sum(queue, (width,height), None, b_buf, dest_buf) 

a_plus_b = np.empty(height,dtype=np.int32) 
cl.enqueue_copy(queue, a_plus_b, dest_buf) 

print(np.sum(b)) 
print(a_plus_b) 
print(np.sum(a_plus_b-np.sum(b))) 

дает выход:

496 
[496 496 496 496 496 496 496 496 496 496 496 496 496 496 496 496 496 496 
496 496 496 496 496 496 496 496 496 496 496 496 496 496 496 496 496 496 
496 496 496 496 496 496 496 496 496 496 496 496 496 496] 
0 

Однако, если я изменить ширину от 32 до 33, массив больше не тот же элемент снова и снова.

528 
[555 557 555 559 560 528 560 560 528 528 528 528 528 528 528 528 528 528 
528 528 528 531 540 569 581 528 705 591 560 560 545 560 560 528 560 528 
528 528 528 528 528 528 528 528 528 528 528 532 533 535] 
752 

Фактически, каждый раз, когда код запускается, он производит другой результат.

528 
[560 560 559 560 560 560 560 528 528 528 528 528 528 528 528 528 528 528 
528 528 528 560 528 514 565 553 621 650 560 560 560 560 560 528 528 528 
528 528 528 528 528 528 528 528 549 528 528 544 528 537] 
724 

В чем причина разницы? Что является не:

ответ

2

Вы работаете в WIDTH x HEIGHT. Для каждого значения X в вашем ядре будут выполняться рабочие элементы WIDTH параллельно с одним и тем же: установка C [X] на 0, а затем обновление в Y-цикле. Все эти рабочие элементы WIDTH будут читать C [X], а затем обновлять их более или менее одновременно. Это «более или менее» является причиной изменений, которые вы наблюдаете.

Ваш алгоритм 1D, и вам нужно запустить только рабочие элементы HEIGHT и передать WIDTH в качестве аргумента ядра. Замените C [X] на регистр «SUM» и сделайте один C [X] = SUM в конце.

+0

Это решило проблему. Я предполагаю, что это то, что я получаю за то, что я ленив и не передаю длину массива как фактический параметр. – user640078