예제와 비슷한 PyOpenCL을 사용하여 감소 합계를 만들려고했습니다 : https://dournac.org/info/gpu_sum_reduction. 모든 값이 1 인 벡터를 합계하려고합니다. 결과는 첫 번째 요소에서 16384 여야합니다. 그러나 일부 지점 만 수집되고있는 것처럼 보입니다. 로컬 색인이 필요합니까? 경쟁 조건이 있습니까 (두 번 실행하면 결과가 동일하지 않습니다)? 다음 코드는 무엇이 잘못 되었습니까?OpenCL의 로컬 메모리 펜스와 글로벌 메모리 펜스의 차이점은 무엇입니까?
import numpy as np
import pyopencl as cl
def readKernel(kernelFile):
with open(kernelFile, 'r') as f:
data=f.read()
return data
a_np = np.random.rand(128*128).astype(np.float32)
a_np=a_np.reshape((128,128))
print(a_np.shape)
device = cl.get_platforms()[0].get_devices(cl.device_type.GPU)[0]
print(device)
ctx=cl.Context(devices=[device])
#ctx = cl.create_some_context() #ask which context to use
queue = cl.CommandQueue(ctx)
mf = cl.mem_flags
a_g = cl.Buffer(ctx, mf.READ_WRITE | mf.COPY_HOST_PTR, hostbuf=a_np)
prg = cl.Program(ctx,readKernel("kernel2.cl")).build()
prg.test(queue, a_np.shape, None, a_g)
cl.enqueue_copy(queue, a_np, a_g).wait()
np.savetxt("teste2.txt",a_np,fmt="%i")
커널은 다음과 같습니다
__kernel void test(__global float *count){
int id = get_global_id(0)+get_global_id(1)*get_global_size(0);
int nelements = get_global_size(0)*get_global_size(1);
count[id] = 1;
barrier(CLK_GLOBAL_MEM_FENCE);
for (int stride = nelements/2; stride>0; stride = stride/2){
barrier(CLK_GLOBAL_MEM_FENCE); //wait everyone update
if (id < stride){
int s1 = count[id];
int s2 = count[id+stride];
count[id] = s1+s2;
}
}
barrier(CLK_GLOBAL_MEM_FENCE); //wait everyone update
}