OpenCL - 維基百科,自由的百科全書

文章推薦指數: 80 %
投票人數:10人

OpenCL(Open Computing Language,開放計算語言)是一個為異構平台編寫程式的框架,此異構平台可由CPU、GPU、DSP、FPGA或其他類型的處理器與硬體加速器所組成。

OpenCL 維基百科,自由的百科全書 跳至導覽 跳至搜尋   提示:此條目的主題不是OpenGL。

OpenCL原作者蘋果公司開發者科納斯組織初始版本2009年8月28日,​12年前​(2009-08-28)穩定版本3.0.10[1](2021年11月19日,​3個月前​(2021-11-19)) 作業系統跨平台類型API許可協定免版稅網站www.khronos.org/openclwww.khronos.org/webcl OpenCL(OpenComputingLanguage,開放計算語言)是一個為異構平台編寫程式的框架,此異構平台可由CPU、GPU、DSP、FPGA或其他類型的處理器與硬體加速器所組成。

OpenCL由一門用於編寫kernels(在OpenCL裝置上執行的函式)的語言(基於C99)和一組用於定義並控制平台的API組成。

OpenCL提供了基於任務分割和資料分割的平行計算機制。

OpenCL類似於另外兩個開放的工業標準OpenGL和OpenAL,這兩個標準分別用於三維圖形和電腦音訊方面。

OpenCL擴充了GPU圖形生成之外的能力。

OpenCL由非盈利性技術組織KhronosGroup掌管。

目次 1歷史 2範例 2.1快速傅立葉變換 2.2平行合併排序法 3參考文獻 4外部連結 5參見 歷史[編輯] OpenCL最初由蘋果公司開發,擁有其商標權,並在與AMD,IBM,Intel和NVIDIA技術團隊的合作之下初步完善。

隨後,蘋果將這一草案提交至KhronosGroup。

2008年6月16日,Khronos的通用計算工作小組成立[2]。

5個月後的2008年11月18日,該工作群組完成了OpenCL1.0規範的技術細節[3]。

該技術規範在由Khronos成員進行審查之後,於2008年12月8日公開發表[4]。

2010年6月14日,OpenCL1.1發布[5]。

範例[編輯] 快速傅立葉變換[編輯] 一個快速傅立葉變換的式子: [6] //createacomputecontextwithGPUdevice context=clCreateContextFromType(NULL,CL_DEVICE_TYPE_GPU,NULL,NULL,NULL); //createacommandqueue queue=clCreateCommandQueue(context,NULL,0,NULL); //allocatethebuffermemoryobjects memobjs[0]=clCreateBuffer(context,CL_MEM_READ_ONLY|CL_MEM_COPY_HOST_PTR,sizeof(float)*2*num_entries,srcA,NULL); memobjs[1]=clCreateBuffer(context,CL_MEM_READ_WRITE,sizeof(float)*2*num_entries,NULL,NULL); //createthecomputeprogram program=clCreateProgramWithSource(context,1,&fft1D_1024_kernel_src,NULL,NULL); //buildthecomputeprogramexecutable clBuildProgram(program,0,NULL,NULL,NULL,NULL); //createthecomputekernel kernel=clCreateKernel(program,"fft1D_1024",NULL); //settheargsvalues clSetKernelArg(kernel,0,sizeof(cl_mem),(void*)&memobjs[0]); clSetKernelArg(kernel,1,sizeof(cl_mem),(void*)&memobjs[1]); clSetKernelArg(kernel,2,sizeof(float)*(local_work_size[0]+1)*16,NULL); clSetKernelArg(kernel,3,sizeof(float)*(local_work_size[0]+1)*16,NULL); //createN-Drangeobjectwithwork-itemdimensionsandexecutekernel global_work_size[0]=num_entries; local_work_size[0]=64; clEnqueueNDRangeKernel(queue,kernel,1,NULL,global_work_size,local_work_size,0,NULL,NULL); 真正的運算:(基於FittingFFTontotheG80ArchitectureArchived2012-03-19atWebCite)[7] //ThiskernelcomputesFFToflength1024.The1024lengthFFTisdecomposedinto //callstoaradix16function,anotherradix16functionandthenaradix4function __kernelvoidfft1D_1024(__globalfloat2*in,__globalfloat2*out, __localfloat*sMemx,__localfloat*sMemy){ inttid=get_local_id(0); intblockIdx=get_group_id(0)*1024+tid; float2data[16]; //startingindexofdatato/fromglobalmemory in=in+blockIdx;out=out+blockIdx; globalLoads(data,in,64);//coalescedglobalreads fftRadix16Pass(data);//in-placeradix-16pass twiddleFactorMul(data,tid,1024,0); //localshuffleusinglocalmemory localShuffle(data,sMemx,sMemy,tid,(((tid&15)*65)+(tid>>4))); fftRadix16Pass(data);//in-placeradix-16pass twiddleFactorMul(data,tid,64,4);//twiddlefactormultiplication localShuffle(data,sMemx,sMemy,tid,(((tid>>4)*64)+(tid&15))); //fourradix-4functioncalls fftRadix4Pass(data);//radix-4functionnumber1 fftRadix4Pass(data+4);//radix-4functionnumber2 fftRadix4Pass(data+8);//radix-4functionnumber3 fftRadix4Pass(data+12);//radix-4functionnumber4 //coalescedglobalwrites globalStores(data,out,64); } Apple的網站上可以發現傅立葉變換的例子[8] 平行合併排序法[編輯] 使用Python3.x搭配PyOpenCL與NumPy importio importrandom importnumpyasnp importpyopenclascl defdump_step(data,chunk_size): """顯示排序過程""" msg=io.StringIO('') div=io.StringIO('') foridx,iteminenumerate(data): ifidx%chunk_size==0: ifidx>0: msg.write('||') div.write('') div.write('--') else: msg.write('') div.write('------') msg.write('{:2d}'.format(item)) out=msg.getvalue() ifchunk_size==1:print(''+'-'*(len(out)-1)) print(out) print(div.getvalue()) msg.close() div.close() defcl_merge_sort_sbs(data_in): """平行合併排序""" #OpenCLkernel函數程式碼 CL_CODE=''' kernelvoidmerge(intchunk_size,intsize,globallong*data,globallong*buff){ //取得分組編號 constintgid=get_global_id(0); //根據分組編號計算責任範圍 constintoffset=gid*chunk_size; constintreal_size=min(offset+chunk_size,size)-offset; globallong*data_part=data+offset; globallong*buff_part=buff+offset; //設定合併前的初始狀態 intr_beg=chunk_size>>1; intb_ptr=0; intl_ptr=0; intr_ptr=r_beg; //進行合併 while(b_ptr=real_size){ //若右側沒有資料,取左側資料堆入緩衝區 buff_part[b_ptr]=data_part[l_ptr++]; }elseif(l_ptr==r_beg){ //若左側沒有資料,取右側資料堆入緩衝區 buff_part[b_ptr]=data_part[r_ptr++]; }else{ //若兩側都有資料,取較小資料堆入緩衝區 if(data_part[l_ptr]



請為這篇文章評分?