大家好,我又来介绍opencl第二弹,opencl新手入门基础知识

其实想用opencl在gpu上快速并行运行你的程序很简单。

1.在你平常写代码的地方准备平台,缓冲区一系列的准备

2.写好自己的核函数,有的是文本的形式,不想写文本就写成一个.cl文件然后读文件

3.讲准备好的参数传入核函数

下面就是实操啦,跟着下面的思路也可以自己完成一个简单的demo

//平台准备
cl_device_id device_id = NULL;
cl_context context = NULL;
cl_command_queue command_queue = NULL;
cl_program program = NULL;
cl_kernel kernel = NULL;

//预先需要定义的变量等
//在float前面需要加cl_是为了与缓冲区和核函数中的对应,float3是以3个float以一个元素的意思,相当于别人给你定义好的结构体你直接用
const float radius = radius_;
int vNum = pMesh_->VertexNumber();
//int vNum = 1;
cl_float3* vertices = (cl_float3*)malloc(sizeof(cl_float3) * vNum);//每个点
cl_float3* vertexNormal = (cl_float3*)malloc(sizeof(cl_float3) * vNum);//每个点的法向
int numFaces = pMesh_->numFace();
//int numFaces = 2;
cl_int3* faceData = (cl_int3*)malloc(sizeof(cl_int3) * numFaces);
cl_float* vertexColorArray = (cl_float*)malloc(sizeof(cl_float)
                                               
//下面可以给你定义的变量们赋值
......省略
                                               
//读文件
std::string kernel_source;
std::fstream ifs;
ifs.open("try2.cl", std::ios::in);
if (ifs) {
	std::istreambuf_iterator<char> begin(ifs);
	std::istreambuf_iterator<char> end;
	kernel_source = std::string(begin, end);
}
ifs.close();

size_t kernel_length = kernel_source.size();
const char* programSource = kernel_source.c_str();

//它可以用来获取指定平台上可用的 OpenCL 设备数量和每个设备的相关信息。
ret = clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_GPU, 1, &device_id, NULL);
//是 OpenCL 中用来创建 OpenCL 上下文的函数。上下文是整个 OpenCL 应用程序的环境的核心,它包含了所有的设备、内存对象、命令队列和其他重要的 OpenCL 对象。
context = clCreateContext(NULL, 1, &device_id, NULL, NULL, &ret);
// 是 OpenCL 中用于创建命令队列的函数之一。命令队列是用于向设备提交命令的对象,这些命令可能包括内核执行、内存操作等。
command_queue = clCreateCommandQueueWithProperties(context, device_id, 0, &ret);
//是OpenCL 中创建程序对象的函数之一。它允许你使用字符串形式的源码来创建 OpenCL 程序,这些源码包含了你编写的 OpenCL 内核函数。
program = clCreateProgramWithSource(context, 1, (const char**)&programSource, NULL, &ret);
//clBuildProgram 是 OpenCL 中用于构建(编译)程序对象的函数。这个函数对通过 clCreateProgramWithSource或clCreateProgramWithBinary创建的程序对象进行编译,生成可执行的内核。
ret = clBuildProgram(program, 1, &device_id, NULL, NULL, NULL);
//编译失败输出失败代码
if (ret != CL_SUCCESS) {
	// 编译失败,输出错误码
	printf("Compilation failed with error code: %d\n", ret);

	// 获取编译日志大小
	size_t log_size;
	clGetProgramBuildInfo(program, device_id, CL_PROGRAM_BUILD_LOG, 0, NULL, &log_size);

	// 分配足够的空间来存储编译日志
	char* log = (char*)malloc(log_size);

	// 获取编译日志
	clGetProgramBuildInfo(program, device_id, CL_PROGRAM_BUILD_LOG, log_size, log, NULL);

	// 输出编译日志
	printf("Compile Log:\n%s", log);

	// 释放分配的内存
	free(log);
}
//是 OpenCL 中用于创建内核对象的函数。内核对象是你在程序中编写的 OpenCL 内核函数的实例。在编译了包含内核函数的程序对象之后,使用 clCreateKernel可以为特定的内核函数创建一个内核对象,从而可以在设备上执行这个内核函数。
kernel = clCreateKernel(program, "collisionDetection", &ret);

//是OpenCL中用于创建内存缓冲区对象的函数。这个函数用于在设备上分配内存,用于存储数据,比如用于计算的输入和输出数据。
//这个内核函数就是执行过程中所有的输入和输出
//CL_MEM_READ_ONLY这个标志表示创建的内存对象是只读的,即在设备端不能写入。通常用于传递输入数据给 OpenCL 核函数。
//CL_MEM_COPY_HOST_PTR这个标志表示在创建内存对象时,使用主机端(CPU)上已有的数据进行初始化。这可以通过提供一个指向主机端数据的指针来实现
// CL_MEM_READ_WRITE表示创建的内存对象可读可写。这意味着在设备端既可以读取也可以写入这块内存。
cl_mem memVertices = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, sizeof(cl_float3) * vNum, vertices, &ret);//只读
cl_mem memVertexNormal = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, sizeof(cl_float3) * vNum, vertexNormal, &ret);
cl_mem memFaceData = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, sizeof(cl_int3)*numFaces, faceData, &ret);
cl_mem memVertexColorArray = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(cl_float) * vNum, NULL, &ret);//可读可写
                                               
//设置函数的参数
ret = clSetKernelArg(kernel, 0, sizeof(float), &radius);//
ret = clSetKernelArg(kernel, 1, sizeof(int), &vNum);//
ret = clSetKernelArg(kernel, 2, sizeof(cl_mem), (void*)&memVertices);
ret = clSetKernelArg(kernel, 3, sizeof(cl_mem), (void*)&memVertexNormal);
ret = clSetKernelArg(kernel, 4, sizeof(int), &numFaces);//
ret = clSetKernelArg(kernel, 5, sizeof(cl_mem), &memFaceData);
ret = clSetKernelArg(kernel, 6, sizeof(cl_mem), (void*)&memVertexColorArray);

//函数执行
size_t global_item_size = vNum;
ret = clEnqueueNDRangeKernel(command_queue, kernel, 1, NULL, &global_item_size, NULL, 0, NULL, NULL);
clFinish(command_queue);
//clEnqueueReadBuffer是OpenCL中用于将设备上的内存缓冲区中的数据读取到主机(CPU)内存的函数。它允许从设备内存中读取数据并将其传输到主机内存中。
cl_float* vertexColorArray_ = (cl_float*)malloc(sizeof(cl_float) * vNum);
ret = clEnqueueReadBuffer(command_queue, memVertexColorArray, CL_TRUE, 0, sizeof(cl_int) * vNum, vertexColorArray_, 0, NULL, NULL);
clFinish(command_queue);
                                               
//释放之前开辟的空间
clReleaseMemObject(memVertices);
clReleaseMemObject(memVertexNormal);
clReleaseMemObject(memFaceData);
clReleaseMemObject(memVertexColorArray);
clReleaseProgram(program);
clReleaseKernel(kernel);
clReleaseCommandQueue(command_queue);
clReleaseContext(context);
free(vertices);
free(vertexNormal);
free(faceData);
free(vertexColorArray);
                                           
-------------------------------------------------
vertexColorArray_就是存储是是我最终运行的结果啦。
                                            

  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值