当前位置: 首页 > 编程日记 > 正文

封装OpenCL类

以上一篇《OpenCL入门测试》为基础,将函数封装到类中,方便调用。

#include <cstdlib>
#include <iostream>
#include <iomanip>
#include <cstring>
#include <cassert>
#include <windows.h>
#define CL_USE_DEPRECATED_OPENCL_1_2_APIS // 定义使用OpenCL 1.2
#include <CL/cl.h>
using namespace std;class COpenCL
{public://const int Size = 38888888;//大小和内存有关,仅作示例const int Size = 2073600;//一帧高清点数float* nums1_h = new float[Size];//动态创建 nums1_h 数组float* nums2_h = new float[Size];//动态创建 nums2_h 数组float* sum_h = new float[Size];  //动态创建 sum_h 数组float* gpu_sum = new float[Size];void Init(void); // 初始化void Close(void);// 关闭,释放资源void CreateBuffer(void);// 创建缓冲区void CreateProgramSource(void);// 创建异构源代码void SetKernelArg(void);// 设置核参数void RunGPU(void);// 运行GPUvoid RunAsCpu(const float *nums1, const float *nums2, float* sum, const int num);// CPU运行函数private:cl_mem nums1_d,nums2_d,sum_d;const int mem_size = sizeof(float) * Size;//计算设备所需存储器size_t global_work_size = Size;//设备需要工作项(线程)cl_int Err;cl_platform_id Selected_Platform_ID; // 已选择平台的IDcl_device_id DevicesID; // GPU设备cl_context Context; // 设备管理cl_command_queue CommandQueue; // 命令队列cl_program Program; // 程序对象cl_kernel Kernel; // 内核对象cl_kernel RunAsGpu;//核函数void SelectedPlatform(void);//选择平台void CreateDevice(void);// 创建GPU设备void CreateContext(void);// 创建设备管理void CreateCommandQueue(void);// 创建命令队列void GetProgramBuildInfo(void);// 获取异构(设备)编译程序信息
};// 全局变量
_LARGE_INTEGER g_iSysFrequency,// 系统频率iStartTestTime; // 开始测试时间// 错误检查宏
#define CheckErr(Err, PrintStr) \
if(Err != CL_SUCCESS)   \{                     \printf("\n\n");   \printf("     ");\printf(PrintStr); \printf("\n\n");   \system("pause");  \exit(1);          \}
//---------------------------------------------------------------------------// 核函数源码字符串
const char *RunAsGpu_Source =
"__kernel void RunAsGpu_Source(__global const float *nums1, __global const float *nums2, __global float* sum)\n"
"{\n"
"int id = get_global_id(0);\n"
"sum[id] = nums1[id] + nums2[id];\n"
"}\n";
//---------------------------------------------------------------------------void COpenCL::RunAsCpu(const float *nums1, const float *nums2, float* sum, const int num)// CPU运行函数
{for (int i = 0; i < num; i++){sum[i] = nums1[i] + nums2[i];}
}void StartTestTime(void)// 开始测量耗时
{QueryPerformanceCounter(&iStartTestTime);//开始计时
}double StopTestTime(int iTimeUnit)// 测量耗时
{_LARGE_INTEGER iStopTime; double fRetTime;QueryPerformanceCounter(&iStopTime);// 读停止时间switch (iTimeUnit){case 0:  fRetTime = (double)(iStopTime.QuadPart - iStartTestTime.QuadPart); // nsbreak;case 1:  fRetTime = (double)((iStopTime.QuadPart - iStartTestTime.QuadPart) / (g_iSysFrequency.QuadPart / 1000000)); // usbreak;case 2:  fRetTime = (double)((iStopTime.QuadPart - iStartTestTime.QuadPart) / (g_iSysFrequency.QuadPart / 1000)); // msbreak;case 3:  fRetTime = (double)((iStopTime.QuadPart - iStartTestTime.QuadPart) / g_iSysFrequency.QuadPart); // Sbreak;}return fRetTime;
}void COpenCL::SelectedPlatform(void)//选择平台
{cl_uint PlatformCount; //平台数cl_platform_id *pTotalPlatformtID;//所有平台数ID// 获取平台数目Err = clGetPlatformIDs(0, 0, &PlatformCount);// 获取平台数CheckErr(Err, "错误: OpenCL获取平台数错误!");if (PlatformCount > 0){cout << "可用平台数量: " << PlatformCount << endl;}else{printf("\n\n     错误: 没有可用OpenCL平台!\n\n");system("pause");exit(0);}// 获取所有平台IDpTotalPlatformtID = new cl_platform_id[PlatformCount];//动态创建所有平台ID数组Err = clGetPlatformIDs(PlatformCount, pTotalPlatformtID, NULL);//获取所有平台ID(列表)CheckErr(Err, "错误: OpenCL获取所有平台ID错误。\n");// 列出所有平台名称printf("\n");cout << "所有平台的名称: \n\n";for (cl_uint i = 0; i < PlatformCount; ++i){// 获取平台名称的长度size_t Platform_Name_Length;Err = clGetPlatformInfo(pTotalPlatformtID[i], CL_PLATFORM_NAME, 0, 0, &Platform_Name_Length);// 获取平台名称字符长度CheckErr(Err, "获取OpenCL平台名称长度错误。\n");// 获取平台名称char *Platform_Name = new char[Platform_Name_Length];//动态创建各平台名称字符串数组的长度Err = clGetPlatformInfo(pTotalPlatformtID[i], CL_PLATFORM_NAME, Platform_Name_Length, Platform_Name, 0);// 获取平台名称CheckErr(Err, "错误: 获取平台名称失败。\n");cout << "    [" << i << "] " << Platform_Name << "\n";// 输出平台名称Selected_Platform_ID = pTotalPlatformtID[0];//总是选第一个delete[] Platform_Name;}delete[] pTotalPlatformtID;
}void COpenCL::CreateDevice(void)// 创建GPU设备
{Err = clGetDeviceIDs(Selected_Platform_ID, CL_DEVICE_TYPE_GPU, 1, &DevicesID, NULL);//获得GPU设备数量CheckErr(Err, "错误: OpenCL创建GPU设备失败!");
}void COpenCL::CreateContext(void)// 创建设备管理
{Context = clCreateContext(0, 1, &DevicesID, NULL, NULL, &Err);CheckErr(Err, "错误: OpenCL创建设备环境失败!");
}void COpenCL::CreateCommandQueue(void)// 创建命令队列
{CommandQueue = clCreateCommandQueue(Context, DevicesID, 0, &Err);CheckErr(Err, "错误: OpenCL创建命令队列失败!");
}void COpenCL::GetProgramBuildInfo(void)// 获取异构(设备)编译程序信息 
{char* build_log; size_t log_size;clGetProgramBuildInfo(Program, DevicesID, CL_PROGRAM_BUILD_LOG, 0, NULL, &log_size);// 获取编译信息长度build_log = new char[log_size + 1];clGetProgramBuildInfo(Program, DevicesID, CL_PROGRAM_BUILD_LOG, log_size, build_log, NULL);// 查询编译信息build_log[log_size] = '\0';printf("\n异构(设备)编译信息:\n\n");cout << build_log << endl;delete[] build_log;
}
//---------------------------------------------------------------------------void COpenCL::Init(void)// 初始化
{SelectedPlatform();// 选择平台CreateDevice();// 创建GPU设备CreateContext();// 创建设备管理CreateCommandQueue();// 创建命令队列
}void COpenCL::CreateBuffer(void)// 创建缓冲区
{for (int i = 0; i < Size; i++)//初始化测试数据 {nums1_h[i] = nums2_h[i] = (float)i;}//创建设备缓冲区StartTestTime();nums1_d = clCreateBuffer(Context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, mem_size, nums1_h, &Err);//nums1_d设备输入nums2_d = clCreateBuffer(Context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, mem_size, nums2_h, &Err);//nums2_d设备输入sum_d   = clCreateBuffer(Context, CL_MEM_WRITE_ONLY, mem_size, NULL, &Err);//sum_d设备输出cout << "\nCPU:传输数据到GPU耗时: " << StopTestTime(2) << " ms" << endl;if (nums1_d == 0 || nums2_d == 0 || sum_d == 0){delete[] nums1_h;delete[] nums2_h;delete[] sum_h;clReleaseMemObject(nums1_d);clReleaseMemObject(nums2_d);clReleaseMemObject(sum_d);clReleaseCommandQueue(CommandQueue);clReleaseContext(Context);printf("\n错误:OpenCL创建设备缓冲区失败!\n\n");system("pause");exit(1);//退出}
}void COpenCL::CreateProgramSource(void)// 创建异构源代码
{size_t Src_size[] = { strlen(RunAsGpu_Source) };//读入源代码数组Program = clCreateProgramWithSource(Context, 1, &RunAsGpu_Source, Src_size, &Err);// 输入设备源程序CheckErr(Err, "错误: OpenCL输入设备源程序失败!");// 编译程序对象(编译异构源代码)Err = clBuildProgram(Program, 1, &DevicesID, NULL, NULL, NULL);// 编译设备源程序CheckErr(Err, "错误: OpenCL编译设备源程序失败!");// 创建设备(核)程序函数 RunAsGpuRunAsGpu = clCreateKernel(Program, "RunAsGpu_Source", &Err);// 创建核函数if (Err != CL_SUCCESS){delete[] nums1_h;delete[] nums2_h;delete[] sum_h;clReleaseMemObject(nums1_d);clReleaseMemObject(nums2_d);clReleaseMemObject(sum_d);clReleaseCommandQueue(CommandQueue);clReleaseContext(Context);clReleaseKernel(RunAsGpu);printf("\n错误:OpenCL创建核函数失败!\n\n");system("pause");exit(1);//退出}GetProgramBuildInfo();// 获取异构(设备)编译程序信息
}void COpenCL::SetKernelArg(void)// 设置核参数
{Err = clSetKernelArg(RunAsGpu, 0, sizeof(cl_mem), &nums1_d);Err |= clSetKernelArg(RunAsGpu, 1, sizeof(cl_mem), &nums2_d);Err |= clSetKernelArg(RunAsGpu, 2, sizeof(cl_mem), &sum_d);CheckErr(Err, "错误: OpenCL输入设备(核)程序函数 RunAsGpu 形参失败!");
}void COpenCL::RunGPU(void)// 运行GPU
{StartTestTime();Err = clEnqueueNDRangeKernel(CommandQueue, RunAsGpu, 1, NULL, &global_work_size, NULL, 0, NULL, NULL);//运行核函数CheckErr(Err, "错误: OpenCL核运算失败!");cout << "GPU 计算耗时: " << StopTestTime(0) << " ns" << endl;StartTestTime();clEnqueueReadBuffer(CommandQueue, sum_d, CL_TRUE, 0, mem_size, gpu_sum, 0, NULL, NULL);//读设备缓冲区cout << "CPU 读回数据耗时: " << StopTestTime(2) << " ms" << endl;
}void COpenCL::Close(void)// 关闭,释放资源
{delete[] gpu_sum;delete[] nums1_h;delete[] nums2_h;delete[] sum_h;clReleaseMemObject(nums1_d);clReleaseMemObject(nums2_d);clReleaseMemObject(sum_d);clReleaseCommandQueue(CommandQueue);clReleaseContext(Context);clReleaseKernel(RunAsGpu);
}
//---------------------------------------------------------------------------int main()
{COpenCL OpenCL;QueryPerformanceFrequency(&g_iSysFrequency);//读系统频率OpenCL.Init();OpenCL.CreateBuffer();OpenCL.CreateProgramSource();OpenCL.SetKernelArg();OpenCL.RunGPU();StartTestTime();OpenCL.RunAsCpu(OpenCL.nums1_h, OpenCL.nums2_h, OpenCL.sum_h, OpenCL.Size);// 运行CPU函数cout << "\nCPU 计算耗时: " << StopTestTime(2) << " ms" << endl;if (memcmp(OpenCL.sum_h, OpenCL.gpu_sum, OpenCL.Size * sizeof(float)) == 0)// 比较结果,数值比较{printf("\n比较GPU和CPU计算数值正确。\n");}else{printf("\n比较GPU和CPU计算数值错误!\n");system("pause");exit(1);//退出    }OpenCL.Close();// 关闭,释放资源// 殿后处理printf("\n");printf("运行成功!\n");printf("\n");system("pause");
}

在 Microsoft Visual C++ 2017 控制台调试通过。

转载于:https://www.cnblogs.com/hbg200/p/10068515.html

相关文章:

linux系统调用 ftruncate设置文件大小

系统调用ftruncate可以将一个文件裁剪为指定的大小&#xff0c;函数描述如下&#xff1a; 头文件&#xff1a;<unistd.h> <sys/types.h>函数使用&#xff1a; int truncate(const char *path, off_t length); int ftruncate(int fd, off_t length);函数参数&…

剑指 offer set 22 数组中的逆序数

总结 1. 题目为归并排序的变形, 不过我完全没想到 2. 在归并排序进行字符组 merge 时, 统计逆序数. merge 后, 两个子数组是有序的了, 下次再 merge 的时候就能以 o(n) 的时间内找到某一个逆序对第二个元素的个数 转载于:https://www.cnblogs.com/xinsheng/p/3564026.html

qt信号发送间隔短而槽耗时多_Qt信号槽问题汇总 - osc_9q1dp3jk的个人空间 - OSCHINA - 中文开源技术交流社区...

1. 发送一次信号&#xff0c;调用多次槽函数问题在同一个类中&#xff0c;多次链接QObject::connect(sender, SIGNAL(signalSender(QString, int)), receiver, SLOT(onSignalSender(QString, int))); 会导致发送一次信号signalSender(QString, int) 多次调用槽函数(onSignalSen…

一劳永逸关闭Windwos默认共享

对于IPC$&#xff0c;找到注册表HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\LSA下的RestrictAnonymous项&#xff0c;并将键值改为1。 对于其它默认共享&#xff0c;在注册表HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters下&#…

springboot 集成mybatis时日志输出

application.properties(yml)中配置的两种方式&#xff1a; 这两种方式的效果是一样的&#xff0c;但是下面一种可以指定某个包下的SQL打印出来&#xff0c;上面这个会全部的都会打印出来。 转载于:https://www.cnblogs.com/z0909y/p/10077565.html

linux文件IO与内存映射:用户空间的IO缓冲区

文章目录用户空间IO缓冲区产生IO缓冲区 描述IO缓冲区的写模式自定义IO缓冲区用户空间IO缓冲区产生 系统调用过程中会产生的开销如下&#xff1a; 切换CPU到内核态进行数据内容的拷贝&#xff0c;从用户态到内核态或者从内核态到用户态切换CPU到用户态 以上为普通到系统调用过…

java zookeeper_Java zookeeper开发实例

1、安装zookeeper下载zk http://archive.cloudera.com/cdh5/cdh/5/配置文件tickTime2000initLimit10syncLimit5# zk数据保存目录dataDir/usr/local/zookeeper/dataclientPort2181启动&#xff1a;bin/zkServer.sh start客户端命令行链接&#xff1a;bin/zkCli.sh2、拷贝zookeep…

【转】Maven Jetty 插件的问题(css/js等目录死锁)的解决

Maven Jetty 插件的问题&#xff08;css/js等目录死锁&#xff0c;不能自动刷新&#xff09;的解决&#xff1a;1. 打开下面的目录&#xff1a;C:\Users\用户名\.m2\repository\org\eclipse\jetty\jetty-webapp\&#xff0c;在进入版本对应的子目录&#xff0c;例如8.1.3.v2012…

ORA-4031错误深入解析

报ORA-4031错误时&#xff0c;我们通常可以根据Oracle无法分配多少字节的内存&#xff0c;来判断共享池碎片的严重程度&#xff0c;以下是4031错误官方的解释&#xff1a;[oracleguoyj ~]$ oerr ORA 403104031, 00000, "unable to allocate %s bytes of shared memory (\&…

buffers与cached的区别

具体参考以下博文&#xff1a; 1、https://www.cnblogs.com/chenpingzhao/p/5161844.html 2、https://blog.csdn.net/heweimingming/article/details/52230293 3、http://www.cnblogs.com/zhoug2020/p/6336453.html 其中3有top命令的详解。转载于:https://www.cnblogs.com/jia…

linux文件IO与内存映射:分散/聚集IO技术(scatter-gather)

前言 根据上文我们学习到的用户空间的IO缓冲区&#xff0c;操作系统为了减少系统调用的次数&#xff0c;节省系统开销&#xff0c;提出了用户空间的IO缓冲区&#xff0c;即为用户空间的文件读写开辟一段可以利用setvbuf配置大小的内存空间来作为文件IO缓冲区。 描述 为了在以…

android jni 调用 java_Android与JNI(二) ---- Java调用C++ 动态调用

目录&#xff1a;1. 简介2. JNI 组件的入口函数3. 使用 registerNativeMethods 方法4. 测试5. JNI 帮助方法6. 参考资料1. 简介Android与JNI(一)已经简单介绍了如何在 android 环境下使用 JNI 了。但是遵循 JNI 开发的基本步骤似乎有点死板&#xff0c;而且得到的本地函数名太…

如何查找并干掉僵尸进程

查找命令&#xff1a;ps -A -o stat,pid,ppid,cmd | grep -e ^[Zz] 找到之后 kill掉&#xff0c;然后用top命令查看是否kill成功&#xff0c;如果失败&#xff0c;kill 父进程。 转载于:https://www.cnblogs.com/kfx2007/p/3572249.html

[转] WINCC教学视频

原文地址http://www.ad.siemens.com.cn/club/bbs/post.aspx?b_id5&a_id1049763&s_id17&num0#anch WinCC 变量归档系列视频&#xff1a; http://www.ad.siemens.com.cn/service/elearning/cn/SerialVideo.aspx?vsid136 WinCC亚洲版高级工程师培训视频&#xff1a;…

UNL(Ubiquitous Navigation Lab)

转载于:https://www.cnblogs.com/Forwithy/p/10080078.html

linux 文件IO与内存映射:内存映射

前言 前面几篇我们学习了用户空间的IO缓冲区,以及IO缓冲区的分散聚合IO技术. 为了减少系统调用的次数&#xff0c;提升系统性能&#xff0c;操作系统开发者门提出了这么多的缓存技术。 但是到这里这些技术同样有不足的地方&#xff1a;不论是读或者写文件&#xff0c;都需要将…

Java网页数据采集器[下篇-数据查询]【转载】

本期概述 上一期我们学习了如何将html采集到的数据存储到MySql数据库中,这期我们来学习下如何在存储的数据中查询我们实际想看到的数据. 数据采集页面 2011-2012赛季英超球队战绩 如果是初学者 以下可能对你有帮助 Java如何操作MySql?在使用java 操作MySql数据库之前 我们需要…

loadrunner 调用java_LoadRunner调用Java程序—性能测试

为了充分利用LoadRunner的场景控制和分析器&#xff0c;帮助我们更好地控制脚本加载过程&#xff0c;从而展现更直观有效的场景分析图表。本次将重点讨论LoadRunner如何调用Java测试代码&#xff0c;完成压力测试。通常我们在执行一些Server的压力测试的时候&#xff0c;总会不…

《The Art of Readable Code》 读书笔记 01

放假前在学校图书馆借了一本新书《The Art of Readable Code》&#xff0c;寒假回来看看&#xff0c;写写其中的Key Idea 、summary和一些读书笔记。 Preface 前言部分主要概况讲了本书的核心思想——Code shoule be easy to understand。接着探讨什么是好代码&#xff0c;是内…

吴裕雄 10-MySQL插入数据

语法以下为向MySQL数据表插入数据通用的 INSERT INTO SQL语法&#xff1a;INSERT INTO table_name ( field1, field2,...fieldN ) VALUES ( value1, value2,...valueN );如果数据是字符型&#xff0c;必须使用单引号或者双引号&#xff0c;如&#xff1a;"value"。 通…

编译内核指定模块,筛选当前模块依赖的组件

关于内核模块编译的过程中&#xff0c;往往我们仅仅需要其中一个小的模块&#xff0c;但是却因为内核源码的庞杂而止步与模块依赖的筛选过程中。 为了更加便捷得对内核各个模块进行管理&#xff0c;这里提供一个小脚本来进行指定模块相关得模块留存&#xff0c;不相关的模块代码…

计算机启动和操作系统加载小话

整个启动和加载过程可分为若干步骤&#xff0c;或者称为若干个状态&#xff0c;或者快照&#xff0c;下面的每一段都是描述一个快照。&#xff08;类似自动状态机&#xff09; 1、电源稳定&#xff08;POWER GOOD&#xff09; 按下启动键后&#xff0c;电源首先启动。为了保证安…

java清空栈_java - 如何使用Intent.FLAG_ACTIVITY_CLEAR_TOP清除活动堆栈?

java - 如何使用Intent.FLAG_ACTIVITY_CLEAR_TOP清除活动堆栈&#xff1f;我已经阅读了几篇关于使用它的帖子&#xff0c;但必须遗漏一些因为它不适合我。 我的活动A在清单中有launchmode “singleTop”。 它启动活动B&#xff0c;启动模式“singleInstance”。 活动B打开浏览器…

「学习笔记-Linux」学习Shell Script

学习Shell Script Table of Contents 1 什么是Shell Scipt 1.1 程序书写1.2 程序执行2 简单Shell练习 2.1 例1 接收用户输入2.2 例2 按日期建立相似名字的文件3 判断式 3.1 测试文件是否存在3.2 test常用选项 3.2.1 文件类型3.2.2 权限3.2.3 文件新旧比较3.2.4 整数&#xff0c…

django admin组件

admin实例 from django.contrib import admin from app01 import models from django.utils.safestring import mark_safe # Register your models here. class UserInfoConfig(admin.ModelAdmin):# 自定义显示的东西def xxx(self):return mark_safe(<a href>xx</a>…

C语言网络编程:close或者shutdown断开通信连接

文章目录前言close函数介绍shutdown函数介绍前言 这里在主要通过实例进行描述close函数在网络编程中的使用 TCP编程模型中客户端或者服务器只要主动通过close发起断开连接的请求&#xff0c;则通信连接可以中断。 可以通过在主进程中抓取通信端的断开信号&#xff0c;比如SIGI…

Await, and UI, and deadlocks! Oh my!

It’s been awesome seeing the level of interest developers have had for the Async CTP and how much usage it’s getting. Of course, with any new technology there are bound to be some hiccups. One issue I’ve seen arise now multiple times is developers acc…

传智播客java基础的习题_传智播客java基础班(集合与IO)阶段测试题

本帖最后由 zhaodecang 于 2016-6-8 19:38 编辑单选题&#xff1a;(每道题目2分)1. ArrayList类的底层数据结构是( )a) 数组结构b) 链表结构 c) 哈希表结构 d) 红黑树结构2. LinkedList类的特点是( )a) 查询快b) 增删快c) 元素不重复 d) 元素自然排序3. Vector类的特点…

$@ 与 $* 差在哪?

$ 与 $* 差在哪&#xff1f; 要说 $ 与 $* 之前&#xff0c;需得先从 shell script 的 positional parameter 谈起...我们都已经知道变量(variable)是如何定义及替换的&#xff0c;这个不用再多讲了。但是&#xff0c;我们还需要知道有些变量是 shell 内定的&#xff0c;且其名…

[源码和文档分享]基于Netty和WebSocket的Web聊天室

一、背景 伴随着Internet的发展与宽带技术的普及&#xff0c;人们可以通过Internet交换动态数据&#xff0c;展示新产品&#xff0c;与人进行沟通并进行电子商务贸易。作为构成网站的重要组成部分&#xff0c;留言管理系统为人们的交流提供了一个崭新的平台。同时&#xff0c;聊…