日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Opencl 并行求和

發(fā)布時(shí)間:2025/3/15 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Opencl 并行求和 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

上周嘗試用opencl求極大值,在網(wǎng)上查到大多是求和,所謂的reduction算法。不過思路是一樣的。

CPP:

   int err = 0;unsigned long int nNumCount = 102400000;int nLocalSize = 256;int nGroupSize = 102400;int nGroup = nGroupSize / nLocalSize;int* pArray = new int[nNumCount];unsigned long int nReal = 0;int nStart = GetTickCount();for (int i=0;i<nNumCount;++i){pArray[i] = i*2;nReal += pArray[i];}cout<<GetTickCount() - nStart<<endl;cl_mem clmemArray = clCreateBuffer(context,CL_MEM_READ_WRITE,sizeof(int) * nNumCount,NULL,NULL);err = clEnqueueWriteBuffer(queue,clmemArray,CL_TRUE,0,sizeof(int)*nNumCount,pArray,0,0,0);cl_mem clmemRes = clCreateBuffer(context,CL_MEM_READ_WRITE,sizeof(int) * nGroup,NULL,NULL);nStart = GetTickCount();err = clSetKernelArg(m_KerCalcRay,0,sizeof(cl_mem),&clmemArray);err = clSetKernelArg(m_KerCalcRay,1,sizeof(cl_mem),&clmemRes);err = clSetKernelArg(m_KerCalcRay,2,sizeof(int)*nLocalSize,0);err = clSetKernelArg(m_KerCalcRay,3,sizeof(int),&nNumCount);size_t localws[1] = {nLocalSize};size_t globalws[1] = {nGroupSize};err = clEnqueueNDRangeKernel(queue,m_KerCalcRay,1,NULL,globalws,localws,0,NULL,NULL);clFinish(queue);int* pRes = new int[nGroup];err = clEnqueueReadBuffer(queue,clmemRes,CL_TRUE,0,sizeof(int)*nGroup,pRes,0,0,0);clFinish(queue);unsigned long int nRes = 0;for(int i=0;i<nGroup;++i){nRes += pRes[i];}
  assert(nRes == nReal);

kernel:

__kernel void ReduceSum(__global int* num,__global int* res,__local int* pData,int nCount) {unsigned int tid = get_local_id(0); unsigned int bid = get_group_id(0); unsigned int gid = get_global_id(0);unsigned int localSize = get_local_size(0); unsigned int globalSize = get_global_size(0);int nRes = 0;while(gid < nCount){nRes += num[gid];gid += globalSize;}pData[tid] = nRes; barrier(CLK_LOCAL_MEM_FENCE);// do reduction in shared memfor(unsigned int s = localSize >> 1; s > 0; s >>= 1) {if(tid < s) {pData[tid] += pData[tid + s];}barrier(CLK_LOCAL_MEM_FENCE);}if(tid == 0)res[bid] = pData[0];}

Reduction求和是這樣一種方法,比如8個(gè)數(shù)0到7依次存放,求和的時(shí)候就是下標(biāo)0和4、1和5、2和6、3和7,求和結(jié)果放到下標(biāo)0、1、2、3中(同步一把barrier(CLK_LOCAL_MEM_FENCE))。然后繼續(xù)就是0和2,、1和3求和結(jié)果放到0、1中。如此往復(fù)、最終結(jié)果就放到下標(biāo)0中啦。

另:我試過循環(huán)展開減少同步次數(shù)、不過效率增長微乎其微。

轉(zhuǎn)載于:https://www.cnblogs.com/slean/p/3770094.html

總結(jié)

以上是生活随笔為你收集整理的Opencl 并行求和的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。