#pragma warning(disable:4996)
#include
#include
#ifdef __APPLE__
#include
#else
#include
#endif
#define ARRAY_SIZE 50000
char *ReadKernelSourceFile(const char *filename, size_t *length) {
FILE *file = NULL;
size_t sourceLength;
char *sourceString;
int ret;
file = fopen(filename, "rb");
if (NULL == file) {
printf("%s at %d :Cant't open %s\n", __FILE__, __LINE__ - 2, filename);
return NULL;
}
fseek(file, 0, SEEK_END);
sourceLength = ftell(file);
fseek(file, 0, SEEK_SET);
sourceString = (char*)malloc(sourceLength + 1); sourceString[0] = '\0';
ret = fread(sourceString, sourceLength, 1, file);
if (0 == ret) {
printf("%s at %d :Cant't open %s\n", __FILE__, __LINE__ - 2, filename);
return NULL;
}
fclose(file);
if (length != 0) {
*length = sourceLength;
}
sourceString[sourceLength] = '\0';
return sourceString;
}
/*
获取平台数据
*/
void getPlatformInfo() {
cl_platform_id *platform;
cl_uint num_platform;
cl_int err;
err = clGetPlatformIDs(0, NULL, &num_platform);
platform = (cl_platform_id *)malloc(sizeof(cl_platform_id) * num_platform);
err = clGetPlatformIDs(num_platform, platform, NULL);
for (int i = 0; i < num_platform; i++)
{
size_t size;
// get name
err = clGetPlatformInfo(platform[i], CL_PLATFORM_NAME, 0, NULL, &size);
char *name = (char *)malloc(size);
err = clGetPlatformInfo(platform[i], CL_PLATFORM_NAME, size, name, NULL);
printf("CL_PLATFORM_NAME:%s\n", name);
// vendor
err = clGetPlatformInfo(platform[i], CL_PLATFORM_VENDOR, 0, NULL, &size);
char *vendor = (char *)malloc(size);
err = clGetPlatformInfo(platform[i], CL_PLATFORM_VENDOR, size, vendor, NULL);
printf("CL_PLATFORM_VENDOR:%s\n", vendor);
// version
err = clGetPlatformInfo(platform[i], CL_PLATFORM_VERSION, 0, NULL, &size);
char *version = (char *)malloc(size);
err = clGetPlatformInfo(platform[i], CL_PLATFORM_VERSION, size, version, NULL);
printf("CL_PLATFORM_VERSION:%s\n", version);
// profile
err = clGetPlatformInfo(platform[i], CL_PLATFORM_PROFILE, 0, NULL, &size);
char *profile = (char *)malloc(size);
err = clGetPlatformInfo(platform[i], CL_PLATFORM_PROFILE, size, profile, NULL);
printf("CL_PLATFORM_PROFILE:%s\n", profile);
// extensions
err = clGetPlatformInfo(platform[i], CL_PLATFORM_EXTENSIONS, 0, NULL, &size);
char *extensions = (char *)malloc(size);
err = clGetPlatformInfo(platform[i], CL_PLATFORM_EXTENSIONS, size, extensions, NULL);
printf("CL_PLATFORM_EXTENSIONS:%s\n", extensions);
//
printf("\n\n");
// clean
free(name);
free(vendor);
free(version);
free(profile);
free(extensions);
}
}
/*
创建平台
创建设备
根据设备创建上下文
*/
cl_context CreateContext(cl_device_id *device) {
cl_int errNum;
cl_uint numPlatforms;
cl_platform_id firstPlatformId;
cl_context context = NULL;
//errNum = clGetPlatformIDs(1, &firstPlatformId, &numPlatforms);
//-----------------------------------------
cl_platform_id *platform;
errNum = clGetPlatformIDs(0, NULL, &numPlatforms);
platform = (cl_platform_id *)malloc(sizeof(cl_platform_id) * numPlatforms);
errNum = clGetPlatformIDs(numPlatforms, platform, NULL);
firstPlatformId = platform[1];
//-----------------------------------------
if (errNum != CL_SUCCESS || numPlatforms <= 0) {
printf("未找到任何OpenCL平台!\n");
}
if (errNum != CL_SUCCESS) {
printf("没有GPU,尝试CPU的OpenCL\n");
errNum = clGetDeviceIDs(firstPlatformId, CL_DEVICE_TYPE_CPU, 1, device, NULL);
}
if (errNum != CL_SUCCESS) {
printf("没有GPU也没有CPU支持OpenCL\n");
return NULL;
}
clGetDeviceIDs(firstPlatformId, CL_DEVICE_TYPE_GPU, 1, device, NULL);
context = clCreateContext(NULL, 1, device, NULL, NULL, &errNum);
if (errNum != CL_SUCCESS) {
printf("创建OpenCL上下文失败\n");
return NULL;
}
return context;
}
/*
在上下文可用的第一个设备中创建命令队列
*/
cl_command_queue CreateCommandQueue(cl_context context, cl_device_id device) {
cl_int errNum;
cl_command_queue commandQueue = clCreateCommandQueue(context, device, 0, NULL);
if (commandQueue == NULL) {
printf("创建命令队列失败\n");
}
return commandQueue;
}
/*
读取内核源码,创建OpenCL程序
*/
cl_program CreateProgram(
cl_context context,
cl_device_id device,
const char *filename
) {
cl_int errNum;
cl_program program;
size_t program_length;
char *const source = ReadKernelSourceFile(filename, &program_length);
program = clCreateProgramWithSource(context, 1, (const char **)&source, NULL, NULL);
if (program == NULL) {
printf("从资源创建OpenCL程序错误");
return NULL;
}
errNum = clBuildProgram(program, 0, NULL, NULL, NULL, NULL);
if (errNum != CL_SUCCESS) {
char buildLog[16384];
clGetProgramBuildInfo(program, device,
CL_PROGRAM_BUILD_LOG,
sizeof(buildLog),
buildLog,
NULL
);
return NULL;
}
return program;
}
/*
创建内存对象(申请内存空间)
*/
bool CreateMemObjects(cl_context context, cl_mem memObjects[3], float *a, float *b) {
memObjects[0] = clCreateBuffer(
context,
CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
sizeof(float)*ARRAY_SIZE, a, NULL
);
memObjects[1] = clCreateBuffer(
context,
CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
sizeof(float)*ARRAY_SIZE, b, NULL
);
memObjects[2] = clCreateBuffer(
context,
CL_MEM_READ_WRITE,
sizeof(float)*ARRAY_SIZE,
NULL, NULL
);
if (memObjects[0] == NULL || memObjects[1] == NULL || memObjects[2] == NULL) {
printf("创建内存对象失败\n");
return false;
}
return true;
}
/*
清除OpenCL资源
*/
void CleanUp(
cl_context context,
cl_command_queue commandQueue,
cl_program program,
cl_kernel kernel,
cl_mem memObjects[3]
) {
for (int i = 0; i < 3; i++) {
if (memObjects[i] != 0) {
clReleaseMemObject(memObjects[i]);
}
}
if (commandQueue != 0) {
clReleaseCommandQueue(commandQueue);
}
if (program != 0) {
clReleaseProgram(program);
}
if (kernel != 0) {
clReleaseKernel(kernel);
}
if (context != 0) {
clReleaseContext(context);
}
}
int main(int argc,char **argv) {
cl_context context = 0;
cl_command_queue commandQueue = 0;
cl_program program = 0;
cl_device_id device = 0;
cl_kernel kernel = 0;
cl_mem memObjects[3] = { 0,0,0 };
cl_int errNum;
//创建OpenCL上下文
context = CreateContext(&device);
if (context == NULL) {
printf("OpenCL上下文创建失败\n");
return 1;
}
//获得OpenCL设备,创建命令队列
commandQueue = CreateCommandQueue(context, device);
if (commandQueue == NULL) {
CleanUp(context, commandQueue, program, kernel, memObjects);
return 1;
}
//创建OpenCL程序
program = CreateProgram(context, device, "vecAdd.cl");
if (program == NULL) {
CleanUp(context, commandQueue, program, kernel, memObjects);
return 1;
}
//创建OpenCL内核
kernel = clCreateKernel(program, "vector_add", &errNum);
if (kernel == NULL) {
printf("创建内核失败\n 错误代码:&d",errNum);
CleanUp(context, commandQueue, program, kernel, memObjects);
return 1;
}
//创建OpenCL内存对象
float result[ARRAY_SIZE];
float a[ARRAY_SIZE];
float b[ARRAY_SIZE];
for (int i = 0; i < ARRAY_SIZE; i++) {
a[i] = (float)i;
b[i] = (float)(i * 2);
}
if (!CreateMemObjects(context, memObjects, a, b)) {
CleanUp(context, commandQueue, program, kernel, memObjects);
return 1;
}
//设置内存参数
errNum = clSetKernelArg(kernel, 0, sizeof(cl_mem),&memObjects[0]);
errNum |= clSetKernelArg(kernel, 1, sizeof(cl_mem), &memObjects[1]);
errNum |= clSetKernelArg(kernel, 2, sizeof(cl_mem), &memObjects[2]);
if (errNum != CL_SUCCESS) {
printf("设置内核参数失败\n");
CleanUp(context, commandQueue, program, kernel, memObjects);
return 1;
}
size_t globalWorkSize[1] = { ARRAY_SIZE };
size_t localWorkSize[1] = { 1 };
//执行内核
errNum = clEnqueueNDRangeKernel(
commandQueue,kernel,
1,NULL,
globalWorkSize,localWorkSize,
0,NULL,NULL
);
if (errNum != CL_SUCCESS) {
printf("内核执行错误\n");
CleanUp(context, commandQueue, program, kernel, memObjects);
return 1;
}
//计算结果拷贝回主机
errNum = clEnqueueReadBuffer(
commandQueue, memObjects[2],
CL_TRUE, 0,
ARRAY_SIZE * sizeof(float),
result, 0, NULL, NULL
);
if (errNum != CL_SUCCESS) {
printf("结果内存回写失败\n");
CleanUp(context, commandQueue, program, kernel, memObjects);
return 1;
}
for (int i = 0; i < ARRAY_SIZE; i++) {
//printf("i = %d : %f\n", i, result[i]);
}
printf("执行程序完成\n");
CleanUp(context, commandQueue, program, kernel, memObjects);
system("pause");
return 0;
}
__kernel void vector_add(
global const float *a,
global const float *b,
global float *result
) {
int n = 100000000;
int gid = get_global_id(0);
for(int i=0;i