高性能计算 OpenCL入门1

高性能计算 OpenCL入门1_第1张图片

#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

 

你可能感兴趣的:(高性能计算 OpenCL入门1)