| OpenCL | ||
|---|---|---|
| Parte deComputación heterogénea | ||
| Información general | ||
| Tipo de programa | Interfaz de programación de aplicaciones,GPGPU | |
| Autor | Apple | |
| Desarrollador | Grupo Khronos | |
| Lanzamiento inicial | 28 de agosto de 2009 | |
| Licencia | Libre de derechos | |
| Información técnica | ||
| Programado en | ||
| Plataformas admitidas | ||
| Versiones | ||
| Última versión estable | 3.0.15[1] (info)(14 de diciembre de 2023 (1 año, 11 meses y 12 días)[1]) | |
| Enlaces | ||
OpenCL (Open Computing Language, en españollenguaje de computación abierto) consta de unainterfaz de programación de aplicaciones y de unlenguaje de programación. Juntos permiten crearaplicaciones con paralelismo a nivel de datos y de tareas que pueden ejecutarse tanto enunidades centrales de procesamiento comounidades de procesamiento gráfico. El lenguaje está basado enC99, eliminando cierta funcionalidad y extendiéndolo con operaciones vectoriales.[2]
Apple creó la especificación original y fue desarrollada en conjunto conAMD,IBM,Intel yNVIDIA. Apple la propuso alGrupo Khronos para convertirla en un estándar abierto y libre de derechos. El 16 de junio de 2008 Khronos creó elCompute Working Group[3] para llevar a cabo el proceso de estandarización. En 2013 se publicó la versión 2.0 del estándar.
OpenCL forma parte deMac OS X v10.6 ('Snow Leopard'),[4] mientras que AMD decidió apoyar OpenCL en lugar de su antigua APIClose to Metal.[5][6] Intel también dispone de su propio entorno de desarrollo y NVIDIA además de tener su propia API para chips gráficos llamada CUDA, también admite OpenCL.
Este ejemplo calcula unaTransformada rápida de Fourier.[2] Las llamadas a la API son las siguientes:
// create a compute context with GPU devicecontext=clCreateContextFromType(CL_DEVICE_TYPE_GPU);// create a work-queuequeue=clCreateWorkQueue(context,NULL,NULL,0);// allocate the buffer memory objectsmemobjs[0]=clCreateBuffer(context,CL_MEM_READ_ONLY|CL_MEM_COPY_HOST_PTR,sizeof(float)*2*num_entries,srcA);memobjs[1]=clCreateBuffer(context,CL_MEM_READ_WRITE,sizeof(float)*2*num_entries,NULL);// create the compute programprogram=clCreateProgramFromSource(context,1,&fft1D_1024_kernel_src,NULL);// build the compute program executableclBuildProgramExecutable(program,false,NULL,NULL);// create the compute kernelkernel=clCreateKernel(program,“fft1D_1024”);// create N-D range object with work-item dimensionsglobal_work_size[0]=n;local_work_size[0]=64;range=clCreateNDRangeContainer(context,0,1,global_work_size,local_work_size);// set the args valuesclSetKernelArg(kernel,0,(void*)&memobjs[0],sizeof(cl_mem),NULL);clSetKernelArg(kernel,1,(void*)&memobjs[1],sizeof(cl_mem),NULL);clSetKernelArg(kernel,2,NULL,sizeof(float)*(local_work_size[0]+1)*16,NULL);clSetKernelArg(kernel,3,NULL,sizeof(float)*(local_work_size[0]+1)*16,NULL);// execute kernelclExecuteKernel(queue,kernel,NULL,range,NULL,0,NULL);
El cómputo en sí es este:
// This kernel computes FFT of length 1024. The 1024 length FFT is decomposed into// calls to a radix 16 function, another radix 16 function and then a radix 4 function__kernelvoidfft1D_1024(__globalfloat2*in,__globalfloat2*out,__localfloat*sMemx,__localfloat*sMemy){inttid=get_local_id(0);intblockIdx=get_group_id(0)*1024+tid;float2data[16];// starting index of data to/from global memoryin=in+blockIdx;out=out+blockIdx;globalLoads(data,in,64);// coalesced global readsfftRadix16Pass(data);// in-place radix-16 passtwiddleFactorMul(data,tid,1024,0);// local shuffle using local memorylocalShuffle(data,sMemx,sMemy,tid,(((tid&15)*65)+(tid>>4)));fftRadix16Pass(data);// in-place radix-16 passtwiddleFactorMul(data,tid,64,4);// twiddle factor multiplicationlocalShuffle(data,sMemx,sMemy,tid,(((tid>>4)*64)+(tid&15)));// four radix-4 function callsfftRadix4Pass(data);fftRadix4Pass(data+4);fftRadix4Pass(data+8);fftRadix4Pass(data+12);// coalesced global writesglobalStores(data,out,64);}