>>数值归并例子2
在OpenCL里,有一个float4向量数据类型,它一次存4个浮点数。我们可以把8192个元素分成2048个float4来进行归并计算。最后再把向量中4个值相加。这种方法大大提高运算效率。速度是之前的4倍多。
主程序(main.py)
import pyopencl as cl import numpy as np if __name__ == '__main__': #要计算的元素个数 Array_size = 8192 #step 0:获取GPU计算设备 platform = cl.get_platforms()[0] devices = platform.get_devices() #step 1:选择设备并创建上下文 context = cl.create_some_context() #step 2:创建命令队列,选择计算设备 queue = cl.CommandQueue(context,devices[0],cl.command_queue_properties.PROFILING_ENABLE) #获取系统信息,我的K600中max_work_group_size=1024 max_work_group_size = devices[0].get_info(cl.device_info.MAX_WORK_GROUP_SIZE) #分组 num_groups = Array_size // max_work_group_size #创建一个包含8192个1的浮点数组 buf_num = np.ones(Array_size,dtype=np.float32) #存储每个向量的结果 buf_out = np.zeros(num_groups//4,dtype=np.float32) num_buf = cl.Buffer(context, cl.mem_flags.READ_ONLY | cl.mem_flags.COPY_HOST_PTR, hostbuf=buf_num) out_buf = cl.Buffer(context, cl.mem_flags.READ_WRITE | cl.mem_flags.COPY_HOST_PTR, hostbuf=buf_out) #为每个组准备一个存放中间计算值的空间,由于是4个浮点数的向量,所以空间4倍 tmp_buf = cl.LocalMemory(Array_size*4) #加载并创建CL程序 f_cl = open("reduction_vector.cl","r") f_buf = f_cl.read() prg = cl.Program(context,f_buf).build() #运行 prg.reduction_vector(queue,(Array_size//4,),(max_work_group_size,),num_buf,tmp_buf,out_buf) #读取计算值 cl.enqueue_copy(queue,buf_out,out_buf) sum=0 for i in range(0,num_groups//4): sum += buf_out[i] print(sum) num_buf.release() out_buf.release() queue.finish()
内核程序(reduction_vector.py)
__kernel void reduction_vector(__global float4* data, __local float4* partial_sums, __global float* output){ int cid = get_local_id(0); int group_size = get_local_size(0); partial_sums[cid] = data[get_global_id(0)]; barrier(CLK_LOCAL_MEM_FENCE); for(int i=group_size/2;i>0;i/=2){ if(cid<i){ partial_sums[cid] += partial_sums[cid+i]; } barrier(CLK_LOCAL_MEM_FENCE); } if(cid==0){ output[get_group_id(0)] = dot(partial_sums[0], (float4)(1.0f)); } }
PyOpenCL示例-05.数值归并