作者: Sam (甄峰) sam_code@hotmail.com
1.
如何判断Device是否支持OpenCL:
想要在设备上运行OpenCL程序,首先要判断此设备是否支持OpenCL,我们先探访如何一步步确认Device是否支持OpenCL.
A. 软件测试:
OpenCL-Z
这个软件会探测Device是否支持OpenCL。并告知Android Version,
Kernel Version, OpenCL Version. OpenCL库的目录和文件, OpenCL库
Release的符号。
B. 查看库文件:
对高通,ARM,PowerVR来说,OpenCL库各不相同。
Qualcomm
Adreno:
/system/vendor/lib/libOpenCL.so or /system/lib/libOpenCL.so (older
devices)
64bit系统,则在:/system/vendor/lib64/libOpenCL.so
ARM Mali:
/system/vendor/lib/egl/libGLES_mali.so
or /system/lib/egl/libGLES_mali.so
64bit: /system/vendor/lib64/egl/libGLES_mali.so
PowerVR:
/system/vendor/lib/libPVROCL.so
可以把这些库pull到本地,使用objdump -T libxxxx.so |
grep clGetDeviceInfo
若可以看到OpenCL 的符号,则表示包含了OpenCL库。
00460f5c g DF
.text 0000005c
clGetDeviceInfo
C. 编程测试:
int main(int argc, char** argv)
{
int sum=0;
char buffer[1024];
int* in,*out;
num_block=N/NUM_THREAD;
in=(int*)malloc(sizeof(int)*N);
out=(int*)malloc(sizeof(int)*num_block);
for(int i=0;i
in[i]=1;
}
Init_OpenCL();
Context_cmd();
Create_Buffer(in);
Create_program();
Set_arg();
Execution();
CopyOutResult(out);
for(int i=0;i
sum+=out[i];
}
printf("\nThere is [%d] block.\n", sum);
clGetPlatformInfo(platform[0],CL_PLATFORM_NAME,sizeof(buffer),buffer,NULL);
printf("\nOpenCL Platform Name: [%s]\n", buffer);
memset(buffer, 0, 1024);
clGetDeviceInfo(devices[0],CL_DEVICE_NAME,sizeof(buffer),buffer,NULL);
printf("\nOpenCL Device Name: [%s]\n", buffer);
return 0;
}
void Init_OpenCL()
{
size_t nameLen1;
char platformName[1024];
err = clGetPlatformIDs(0, 0, &num_platform);
platform=(cl_platform_id*)malloc(sizeof(cl_platform_id)*num_platform);
err = clGetPlatformIDs(num_platform, platform, NULL);
err=clGetDeviceIDs(platform[0],CL_DEVICE_TYPE_GPU,0,NULL,&num_device);
devices=(cl_device_id*)malloc(sizeof(cl_device_id)*num_device);
err=clGetDeviceIDs(platform[0],CL_DEVICE_TYPE_GPU,num_device,devices,NULL);
}
void Context_cmd()
{
context=clCreateContext(NULL,num_device,devices,NULL,NULL,&err);
cmdQueue=clCreateCommandQueue(context,devices[0],0,&err);
}
void Create_Buffer(int *data)
{
buffer=clCreateBuffer(context,CL_MEM_READ_ONLY|CL_MEM_COPY_HOST_PTR,sizeof(int)*N,data,&err);
sum_buffer=clCreateBuffer(context,CL_MEM_WRITE_ONLY,sizeof(int)*num_block,0,&err);
}
void Create_program()
{
program=clCreateProgramWithSource(context, LEN(src), src,
NULL, NULL);
err=clBuildProgram(program,num_device,devices,NULL,NULL,NULL);
kernel = clCreateKernel(program, "redution", NULL);
}
void Set_arg()
{
err=clSetKernelArg(kernel,0,sizeof(cl_mem),&buffer);
err=clSetKernelArg(kernel,1,sizeof(cl_mem),&sum_buffer);
err=clSetKernelArg(kernel,2,sizeof(int)*NUM_THREAD,NULL);
}
void Execution()
{
const size_t globalWorkSize[1]={N};
const size_t localWorkSize[1]={NUM_THREAD};
err=clEnqueueNDRangeKernel(cmdQueue,kernel,1,NULL,globalWorkSize,localWorkSize,0,NULL,NULL);
clFinish(cmdQueue);
}
void CopyOutResult(int*out)
{
err=clEnqueueReadBuffer(cmdQueue,sum_buffer,CL_TRUE,0,sizeof(int)*num_block,out,0,NULL,NULL);
}
如果运行正常,获取到Device Name:
则证明从Driver, 到library都是正常的,可以运行OpenCL。