【OpenCL开发入门】03 - 使用NVIDIA CUDA GPU 进行乘法运行算


本系列文章汇总:

  1. 《【OpenCL开发入门】01 - 搭建Visual Studio 2022+OpenCL开发环境》
  2. 《【OpenCL开发入门】02 - 获取当前设备所有OpenCL的信息》
  3. 《【OpenCL开发入门】03 - 使用NVIDIA CUDA GPU 进行乘法运行算》

这个代码昨晚调试到半夜2点多,还是没搞出来,虽然不爽,但实在困得不行了去睡觉了。
今天早上10点多,起床吃完早餐,又重新检查一遍代码,一眼就看出问题所在。
昨晚出问题是因为,初始化数组被我粗心敲错了,
被我写成了:int* Data_a = new int(Data_len);
正确应该是:int* Data_a = new int[Data_len];
这说明,脑子不清晰的时候,千万别写代码,即便出错了,也会检查不出来。

好了,直接贴代码吧:

#include <cstdlib>
#include <iostream>
#include <iomanip>
#include <cstring>
#include <cassert>#include <CL/cl.h>using namespace std;static string use_platform_str[4] = { "NVIDIA","Graphics","Core", "FPGA" };
static int use_platform_id = 0;#define DATA_X  21
#define DATA_Y  21// 检查返回值错误
#define CHECK_ERRORS(ERR) \if(ERR != CL_SUCCESS){ \cerr << "OpenCL error code: " << ERR << "  file: " << __FILE__  << "  line: " << __LINE__ << ".\nExiting..." << endl; \exit(1); \}int main(int argc, const char** argv)
{cl_int err = 0;// 1. 获取平台数量cl_uint platforms_num;err = clGetPlatformIDs(0, nullptr, &platforms_num);CHECK_ERRORS(err);int select_platform_id = platforms_num;// 2. 获取所有平台的信息if (platforms_num > 0) {cl_platform_id* platforms = new cl_platform_id[platforms_num];err = clGetPlatformIDs(platforms_num, platforms, nullptr);CHECK_ERRORS(err);cout << "OpenCL Platform Info:" << endl;// 3. 遍历获取各个平台的信息for (int i = 0; i < platforms_num; i++){// 3.1 获取 platform name的长度size_t length = 0;err = clGetPlatformInfo(platforms[i], CL_PLATFORM_NAME, 0, nullptr, &length);CHECK_ERRORS(err);// 3.2 根据name的长度分配char* value = new char[length];err = clGetPlatformInfo(platforms[i], CL_PLATFORM_NAME, length, value, nullptr);CHECK_ERRORS(err);cout << "    [" << i << "]: " << value << endl;if (strstr(value, use_platform_str[use_platform_id].c_str()) != nullptr) {select_platform_id = i;cout << "\n★ Find The Core(" << select_platform_id << "): " << value << endl;break;}}if (select_platform_id == platforms_num) {cout << "\n☆ Can't Find The Core: " << use_platform_str[use_platform_id].c_str() << endl;exit(-1);}// 4. 创建平台上下文cl_platform_id platform = platforms[select_platform_id];delete[] platforms;cl_context_properties ctx_prop[3] = { CL_CONTEXT_PLATFORM, (cl_context_properties)platform, 0 };cl_context ctx = clCreateContextFromType(ctx_prop, CL_DEVICE_TYPE_GPU, NULL, NULL, &err);CHECK_ERRORS(err);// 5. 获取平台设备数目size_t devices_size = 0;err = clGetContextInfo(ctx, CL_CONTEXT_DEVICES, 0, NULL, &devices_size);CHECK_ERRORS(err);// 6. 申请平台设备数组, 获取所有设备信息cl_device_id* devices = new cl_device_id[devices_size];err = clGetContextInfo(ctx, CL_CONTEXT_DEVICES, devices_size, devices, NULL);CHECK_ERRORS(err);// 7. 读取 .cl 程序源码FILE* fp;fopen_s(&fp, "code.cl", "rb");fseek(fp, 0, SEEK_END);              // 定位到文档结尾size_t code_size = ftell(fp);        // 统计文档大小fseek(fp, 0, SEEK_SET);                // 重新定位到文档开头char* code = new char[code_size + 1];char c, * p = code;while ((c = fgetc(fp)) != EOF) {   // 读取文件内容*p++ = c;}*p = '\0';fclose(fp);// 8. 初始化程序cl_program  program = clCreateProgramWithSource(ctx, 1, (const char**)&code, &code_size, &err);CHECK_ERRORS(err);// 9. 编译程序err = clBuildProgram(program, 1, devices, NULL, NULL, NULL);CHECK_ERRORS(err);// 10. 创建内核 cl_kernel kernel = clCreateKernel(program, "multiply", &err);  // 注意此处必须是函数名CHECK_ERRORS(err);// 11. 创建命令队列cl_command_queue command_q = clCreateCommandQueue(ctx, devices[0], 0, &err);CHECK_ERRORS(err);// 12. 初始化数据int Data_len = DATA_X * DATA_Y;int Data_size = Data_len * sizeof(int);int* Data_a = new int[Data_len];int* Data_b = new int[Data_len];memset(Data_a, 0, Data_size);memset(Data_b, 0, Data_size);for (int i = 0; i < DATA_X; i++) {for (int j = 0; j < DATA_Y; j++){if (i <= DATA_X / 2 && j <= DATA_Y/2) {Data_a[i + j * DATA_X] = i + j;                                   // 左上角Data_a[(DATA_X - i - 1) + j * DATA_X] = i + j;                 // 右上角Data_a[(DATA_X - i - 1) + (DATA_Y - j - 1) * DATA_X] = i + j;  // 右下角Data_a[i + (DATA_Y - j - 1) * DATA_X] = i + j; // 左下角}}}cout << "源数据:\n";for (int i = 0; i < Data_len; i++){if (i % DATA_X == 0) cout << endl;cout.setf(ios::left);       //设置对齐方式为left cout.width(5);                //设置宽度为7,不足用空格填充 cout << Data_a[i];}// 13. 创建buffercl_mem Data_mem_a = clCreateBuffer(ctx, CL_MEM_ALLOC_HOST_PTR | CL_MEM_READ_ONLY, Data_size, NULL, &err); CHECK_ERRORS(err);cl_mem Data_mem_b = clCreateBuffer(ctx, CL_MEM_READ_WRITE, Data_size, NULL, &err); CHECK_ERRORS(err);// 14. 将数据写入buffer队列err = clEnqueueWriteBuffer(command_q, Data_mem_a, CL_TRUE, 0, Data_size, Data_a, 0, NULL, NULL); CHECK_ERRORS(err);err = clEnqueueWriteBuffer(command_q, Data_mem_b, CL_TRUE, 0, Data_size, Data_b, 0, NULL, NULL); CHECK_ERRORS(err);// 15. 设置内核参数err = clSetKernelArg(kernel, 0, sizeof(cl_mem), &Data_mem_a); CHECK_ERRORS(err);err = clSetKernelArg(kernel, 1, sizeof(cl_mem), &Data_mem_b); CHECK_ERRORS(err);// 16. 将内核放入命令队列size_t global_work_size[] = { Data_len };size_t local_work_size[] = { 1 };err = clEnqueueNDRangeKernel(command_q, kernel, 1, NULL, &global_work_size[0], &local_work_size[0], 0, NULL, NULL);CHECK_ERRORS(err);// 17. 等待队列命令执行完毕err = clFinish(command_q); CHECK_ERRORS(err);// 18. 取出计算后的数据err = clEnqueueReadBuffer(command_q, Data_mem_b, CL_TRUE, 0, Data_size, Data_b, 0, NULL, NULL); CHECK_ERRORS(err);// 19. 打印计算后的结果cout << "\n\n计算后的数据:\n";for (int i = 0; i < Data_len; i++){if (i % DATA_X == 0) cout << endl;cout.setf(ios::left);     //设置对齐方式为left cout.width(5);                //设置宽度为7,不足用空格填充 cout << Data_b[i];}cout << endl;err = clReleaseMemObject(Data_mem_a);  CHECK_ERRORS(err);err = clReleaseMemObject(Data_mem_b);  CHECK_ERRORS(err);err = clReleaseProgram(program); CHECK_ERRORS(err);err = clReleaseKernel(kernel);  CHECK_ERRORS(err);err = clReleaseCommandQueue(command_q); CHECK_ERRORS(err);err = clReleaseContext(ctx); CHECK_ERRORS(err);delete[] Data_a;delete[] Data_b;}return 0;
}

code.cl 源码为:

__kernel void multiply(__global const int *a, __global int *b)
{/* get_global_id(0) 返回当前线程的ID号 */const int gid = get_global_id(0);b[gid] = a[gid] * a[gid];
}

编译运行结果:

《【OpenCL开发入门】02 - 获取当前设备所有OpenCL的信息》
《【OpenCL开发入门】03 - 使用NVIDIA CUDA GPU 进行乘法运行算》
结合这两个实例,如果你确实是一行一行代码手敲过来的,不是粘贴复制的话,想必,你现在已经对OpenCL 有所了解了,
只是如果要写更高深的算法的话,可能写不出来,所以,我们还需要对OpenCL进行深入了解下。
所以,接下来的文章,我们会把前面涉及到的函数,以及 cl 的语法,都一个个分析下,尽量搞清楚搞明白。

加油!

【OpenCL开发入门】03 - 使用NVIDIA CUDA GPU 进行乘法运行算相关推荐

  1. TensorRT:在NVIDIA各种GPU硬件平台下运行的高性能推理C++库【Pytorch->ONNX->TensorRT】【实现神经网络提速(读取ONNX模型并运行)】【目前对ONNX的支持最好】

    tensorRT 基本网络构建 创建builder 创建network 创建config network添加输入 network添加层,绑定输入 network mark output,指定输出节点 ...

  2. 【区块链开发入门】(四) Truffle详解篇2

    由于本篇篇幅较长,因此转为两篇文章.Truffle详解篇篇1请见:link 目录导航页 [区块链开发入门](一) 以太坊的搭建与运行 [区块链开发入门](二) 以太坊的编程接口 [区块链开发入门](三 ...

  3. 【区块链开发入门】(三) Solidity合约编译、部署

    目录导航页 [区块链开发入门](一) 以太坊的搭建与运行 [区块链开发入门](二) 以太坊的编程接口 [区块链开发入门](三) Solidity合约编译.部署 [区块链开发入门](四) Truffle ...

  4. OpenCL编程(1)- 开发环境搭建(NVIDIA GPU+Win10篇)

    基于NVIDIA GPU的OpenCL开发环境搭建的步骤如下: 1.下载安装显卡驱动 使用鲁大师或驱动精灵下载安装与显卡型号相适应的显卡驱动并安装,若采用默认路径安装,则在路径C:\Program F ...

  5. [人工智能-深度学习-41]:开发环境 - GPU进行训练安装与搭建(Pytroch、TensorFlow、Nvidia CUDA)详细过程

    作者主页(文火冰糖的硅基工坊):文火冰糖(王文兵)的博客_文火冰糖的硅基工坊_CSDN博客 本文网址:https://blog.csdn.net/HiWangWenBing/article/detai ...

  6. 【并行计算-CUDA开发】从零开始学习OpenCL开发(一)架构

    多谢大家关注 转载本文请注明:http://blog.csdn.net/leonwei/article/details/8880012 本文将作为我<从零开始做OpenCL开发>系列文章的 ...

  7. Nvidia CUDA初级教程4 GPU体系架构概述

    Nvidia CUDA初级教程4 GPU体系架构概述 视频:https://www.bilibili.com/video/BV1kx411m7Fk?p=5 讲师:周斌 本节内容: 为什么需要GPU 三 ...

  8. 我想使用 OctaneRender,但我没有 NVIDIA 显卡。是否支持 OpenCL 兼容卡(AMD 和 Intel GPU)?

    还没有.OctaneRender 需要支持 CUDA 的 NVIDIA 显卡才能渲染.正在努力吸收来自 AMD 和英特尔的 GPU,以用于 OctaneRender 的未来版本.并允许这些与 Octa ...

  9. Jetson Nano开发深度学习实践(一):《基于NVIDIA...开发入门》在jetson_nano开发中可能会遇到的问题1:安装Protobuf,NVIDIA-caffe和Digits

    写在前面 NVIDIA caffe 是NVIDIA维护的caffe的一个分支,有很多便于部署在边缘端的特性,详细信息去NVIDIA的github看吧:https://github.com/NVIDIA ...

最新文章

  1. Java设计模式:单例模式
  2. HttpServletResponse对象(一)
  3. GitHub推出云端IDE,几秒完成开发环境配置,今后可以在浏览器里使用VS Code了
  4. Mac+docker+flask
  5. (转)IE的box模型显示bug
  6. string转换bigdecimal_使用MapStruct处理恼人的bean转换
  7. Phonegap 极光推送api 服务器端推送代码
  8. 求二进制数中1的个数
  9. go 切片取最后一个元素_深挖 Go 之 forrange 排坑指南
  10. 在Linux上运行ASP.NET vNext
  11. Ubuntu Linux 下 Ffmpeg 及 Mencoder 安装使用小结
  12. 网卡5790c linux驱动,(支持所有硬件、无需连接宽带)e驱动 v5.21 WIN7 32bit专版驱动包...
  13. 国产cpu芯片架构和指令集
  14. 面试之防火墙软硬件架构
  15. 巨星传奇更新招股书:业务绑定歌手周杰伦 上半年营收降24%
  16. iOS14.0验证已关闭!
  17. IE浏览器默认主页被篡改,无法改回
  18. 名编辑电子杂志大师教程 | 隐藏不需要的功能按钮
  19. 利用泰勒公式求sin(x)近似值(Python)
  20. 服务器2008系统如何设置休眠时间,Win7休眠和睡眠怎么开启(Win2008)

热门文章

  1. IDEA Shelve Silently 静默搁置
  2. 【分布式】Chubby论文解读
  3. 纽约警察局从社交网络中数据挖掘犯罪活动信息
  4. java代码美化json格式
  5. 灾难后中国文化的反思
  6. python的文件格式有两种,*.py和*.pyw,它们有什么不同
  7. NPDP考试资料汇总
  8. 计算机体系结构基础知识介绍之缓存性能的十大进阶优化之减少命中时间和流水线访问和多组缓存增加带宽(三)
  9. 【图像隐藏】基于LDPC编码译码改进DCT变换算法实现水印嵌入提取matlab源码
  10. 基于逻辑回归/决策树/随机森林/多层感知分类器/xgboost/朴素贝叶斯分类的资讯多分类性能对比