当前位置: 首页 > news >正文

OpenCL编程指南-10.2使用C++包装器API的矢量相加示例

选择OpenCL平台并创建一个上下文

建立OpenCL的第一步是选择一个平台。第2章介绍过,OpenCL使用了ICD模型,其中可以有多个OpenCL实现在一个系统上并存。类似于HelloWorld示例,这个矢量相加程序展示了选择OpenCL平台的一种最简单的方法:选择第一个可用的平台。

首先,调用cl::Platform::get()得到平台列表:

std::vector<cl::Platform> platformList;
cl::Platform::get(&platformList);

得到平台列表之后,这个例子会调用cl::Context()创建一个上下文。cl::Context ()调用会尝试由一个GPU设备创建上下文。如果失败,程序会产生一个异常,这个程序使用了OpenCL C++包装器异常特性,以一个错误消息终止。创建上下文的代码如下:

cl_context_properties cprops[] = (CL_CONTEXT_PLATFORM,(cl_context_properties)(platformList[0])(),0);
cl::Context context(CL_DEVICE_TYPE_GPU, cprops);   

选择一个设备并创建命令队列

选择一个平台并创建上下文之后,矢量相加应用程序的下一步是选择一个设备,并创建一个命令队列。第一个任务是查询与之前所创建上下文关联的设备集合。可以通过cl::Context::getInfo<CL_CONTEXT_DEVICES >()调用来查询,这会返回与上下文关联的设备std::vector。

在继续学习后面的内容之前,先来了解getInfo()方法,因为它遵循了C++包装器API中通用的一种模式。一般来说,对于一个支持查询接口的CAPl对象(例如,查询接口为clGetXXInfo(),其中xx是所查询C API对象的名),任何表示这样一个CAPI对象的C++包装器API对象都有相应的一个接口,形式如下:

template <cl_int> typename
detail::param_traits<detail::cl_XX_info, name>::param_type
cl::Object::getInfo(void);

乍一看可能会让你有些害怕,因为这里使用了一种称为特征类(traits)的C++模板技术(这里用于关联clGetXXInfo()提供的共享功能),不过,由于使用这些getInfo()函数的程序在实际中从来不需要引用特征类组件,所以对于开发人员编写的代码没有任何影响。需要指出的重要一点是,所有对应一个底层C API对象的C++包装器API对象都有一个模板方法,名为getInfo(),以查询的cl_xx_info枚举值作为其模板参数。其效果是可以静态检查所请求的值是否合法,也就是说,一个特定的getInfo()方法只接受相应cl_xx_info枚举中定义的值。通过使用这种特征类技术,getInfo()函数可以自动推导出结果类型。

再来看矢量相加示例,要为关联的一组设备查询一个上下文,可以用CL_CONTEXT_DEVICES限定相应的cl::Context::getInfo(),返回std::vector<cl::Device>。通过以下代码可以说明:

//Query the set of devices attached to the context
std::vector<cl::Device> device =context.getInfo<CL_CONTEXT_DEVICES>();

注意:利用C++包装器API查询方法,现在不再需要先查询上下文来找出需要多大的空间存储设备列表,然后再提供另一个查询调用得到具体的设备。所有这些都隐藏在C++包装器API的一个简单的通用接口中。

选择设备集合之后,可以用cl::CommandQueue()创建一个命令队列,为简单起见,这里选择第一个设备:

//Create command-queue
cl::CommandQueue queue(context, device[0], 0);

创建和构建程序对象

矢量相加示例中的下一步是使用cl::Program()由OpenCL C内核源代码创建一个程序对象(矢量相加示例的内核源代码在本章最后的代码清单2-1中给出,这里不再重复)。程序对象用内核源代码加载,然后使用cl::Program::build()编译这个代码,以便在与上下文关联的设备上执行。下面给出相应的代码:

cl::Program::Sources sources(1,std::make_pair(kernelSourceCode,0));
cl::Program program(context, sources);
program.build(devices);

与其他C++包装器API调用类似,如果出现错误,则会有一个异常,程序将退出。

创建内核和内存对象

要执行OpenCL计算内核,需要在OpenCL设备上可访问的内存中分配内核函数的参数,这里就是缓冲区对象。这些缓冲区对象使用cl::Buffer()创建。对于输入缓冲区,我们使用CL_MEM_COPY_FROM_HOST_PTR来避免额外的调用来移动输人数据。对于输出缓冲区(即矢量相加的结果),则使用CL_MEM_USE_HOST_PTR,这要求将结果缓冲区映射到宿主机内存以便访问结果。可以使用以下代码来分配这些缓冲区:

cl::Buffer aBuffer = cl::Buffer(context,CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,BUFFER_SIZE * sizeof(int),(void *) &A[0]);cl::Buffer bBuffer = cl::Buffer(context,CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,BUFFER_SIZE * sizeof(int),(void *) &B[0]);cl::Buffer cBuffer = cl::Buffer(context,CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR,BUFFER_SIZE * sizeof(int),(void *) &C[0]);

利用cl::Kernel()调用创建内核对象:

cl::Kernel kernel(program, "vadd");

执行矢量相加内核

既然已经创建了内核和内存对象,矢量相加程序终于可以将内核人队等待执行了。内核函数的所有参数都要使用cl::Kernel:setArg()方法来设置。根据C API中的clSetKernelArg(),这个函数的第一个参数是内核函数参数索引。vadd()内核有3个参数(a、b和c),分别对应索引0、1和2。将之前创建的内存对象传入这个内核对象:

kernel.setArg(0, aBuffer);
kernel.setArg(1, bBuffer);
kernel.setArg(2, cBuffer);

与以往一样,设置内核参数之后,矢量相加示例使用命令队列将内核入队等待在设备上执行。这是通过调用cl::CommandQueue::enqueueNDRangeKernel()完成的。全局和局部工作大小使用cl::Range()传递。

对于局部工作大小,使用cl::Range()对象的一个特殊实例cl::NullRange,顾名思义,它对应于C API中传递NULL,允许运行时为设备确定最佳的工作组大小和请求的全局工作大小。

queue.enqueueNDRangeKernel(kernel,cl::NullRange,cl::NDRange(BUFFER_SIZE),cl::NullRange);

将内核入队等待执行并不意味着内核会立即执行。可以使用cl::CommandQueue::flush()或cl::CommandQueue::finish()强制提交到设备立即执行。不过,由于这个矢量相加示例只是要显示结果,所以它使用了一个阻塞的cl::CommandQueue::enqueueMapBuffer(),将输出缓冲区映射到一个宿主机指针:

int * output = (int *)queue.enqueueMapBuffere(cBuffer,CL_TRUE, //blockCL_MAP_READ,0,BUFFER_SIZE * sizeof(int));

宿主机应用程序再处理output 指向的数据,一旦完成,必须用cl::CommandQueue::enqueueUnmapMemObj()调用释放映射的内存:

err = queue.enqueueUnmapMemObject(cBuffer,(void *)output);

代码示例

#define __CL_ENABLE_EXCEPTIONS#include <CL/cl.hpp>#include <cstdio>
#include <cstdlib>
#include <iostream>#define BUFFER_SIZE 20int A[BUFFER_SIZE];
int B[BUFFER_SIZE];
int C[BUFFER_SIZE];static char
kernelSourceCode[] =
"__kernel void                                                               \n"
"vadd(__global int * a, __global int * b, __global int * c)                                                                     \n"
"{                                                                           \n"
"    size_t i =  get_global_id(0);                                           \n"
"                                                                            \n"
"    c[i] = a[i] + b[i];                                                     \n"
"}                                                                           \n"
;int
main(void)
{cl_int err;// Initialize A, B, Cfor (int i = 0; i < BUFFER_SIZE; i++) {A[i] = i;B[i] = i * 2;C[i] = 0;}try {std::vector<cl::Platform> platformList;// Pick platformcl::Platform::get(&platformList);// Pick first platformcl_context_properties cprops[] = {CL_CONTEXT_PLATFORM, (cl_context_properties)(platformList[0])(), 0 };cl::Context context(CL_DEVICE_TYPE_GPU, cprops);// Query the set of devices attched to the contextstd::vector<cl::Device> devices = context.getInfo<CL_CONTEXT_DEVICES>();// Create and program from sourcecl::Program::Sources sources(1, std::make_pair(kernelSourceCode, 0));cl::Program program(context, sources);// Build programprogram.build(devices);// Create buffer for A and copy host contentscl::Buffer aBuffer = cl::Buffer(context,CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,BUFFER_SIZE * sizeof(int),(void*)&A[0]);// Create buffer for B and copy host contentscl::Buffer bBuffer = cl::Buffer(context,CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,BUFFER_SIZE * sizeof(int),(void*)&B[0]);// Create buffer for that uses the host ptr Ccl::Buffer cBuffer = cl::Buffer(context,CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR,BUFFER_SIZE * sizeof(int),(void*)&C[0]);// Create kernel objectcl::Kernel kernel(program, "vadd");// Set kernel argskernel.setArg(0, aBuffer);kernel.setArg(1, bBuffer);kernel.setArg(2, cBuffer);// Create command queuecl::CommandQueue queue(context, devices[0], 0);// Do the workqueue.enqueueNDRangeKernel(kernel,cl::NullRange,cl::NDRange(BUFFER_SIZE),cl::NullRange);// Map cBuffer to host pointer. This enforces a sync with // the host backing space, remember we choose GPU device.int* output = (int*)queue.enqueueMapBuffer(cBuffer,CL_TRUE, // block CL_MAP_READ,0,BUFFER_SIZE * sizeof(int));for (int i = 0; i < BUFFER_SIZE; i++) {std::cout << C[i] << " ";}std::cout << std::endl;// Finally release our hold on accessing the memoryerr = queue.enqueueUnmapMemObject(cBuffer,(void*)output);// There is no need to perform a finish on the final unmap// or release any objects as this all happens implicitly with// the C++ Wrapper API.}catch (cl::Error err) {std::cerr<< "ERROR: "<< err.what()<< "("<< err.err()<< ")"<< std::endl;return EXIT_FAILURE;}return EXIT_SUCCESS;
}

在这里插入图片描述

相关文章:

OpenCL编程指南-10.2使用C++包装器API的矢量相加示例

选择OpenCL平台并创建一个上下文 建立OpenCL的第一步是选择一个平台。第2章介绍过&#xff0c;OpenCL使用了ICD模型&#xff0c;其中可以有多个OpenCL实现在一个系统上并存。类似于HelloWorld示例&#xff0c;这个矢量相加程序展示了选择OpenCL平台的一种最简单的方法&#xf…...

mysql数据库,字符串使用双引号““导致报错,使用单引号‘‘不报错,Unknown column ‘user-test‘ in ‘where clause‘

文章目录 一、完整报错二、报错数据三、报错原因四、解决方式1、更改执行sql2、更改sql数据校验模式&#xff08;改为默认校验&#xff09; 一、完整报错 > 1054 - Unknown column user-test in where clause二、报错数据 SELECT * FROM config_info WHERE config_info.da…...

[华为云云服务器评测] 华为云耀云服务器 Java、node环境配置

系列文章目录 第一章 [linux实战] 华为云耀云服务器L实例 Java、node环境配置 文章目录 系列文章目录前言一、任务拆解二、修改密码三、配置安全规则四、远程登录并更新apt五、安装、配置JDK环境5.1、安装openjdk,选择8版本5.2、检查jdk配置 六、安装、配置git6.1、安装git6.2…...

中企绕道突破封锁,防不胜防 | 百能云芯

韩国的财经媒体Business Korea最新报道指出&#xff0c;尽管美方在《通胀削减法案》&#xff08;IRA&#xff09;的补贴中排除了中国&#xff0c;但中国企业正通过多种方式积极应对美国在半导体和电动汽车电池领域的封锁&#xff0c;这包括建立合资企业、设立生产基地以及开展技…...

动手实践:从栈帧看字节码是如何在 JVM 中进行流转的

Java全能学习面试指南&#xff1a;https://www.javaxiaobear.cn/ 前面我们提到&#xff0c;类的初始化发生在类加载阶段&#xff0c;那对象都有哪些创建方式呢&#xff1f;除了我们常用的 new&#xff0c;还有下面这些方式&#xff1a; 使用 Class 的 newInstance 方法。使用…...

PEX装机

目录 一、PXE是什么&#xff1f; 二、PXE的组件&#xff1a; vsftpd/httpd/nfs tftp dhcp 三、配置vsftpd 四、配置tftp 1.安装tftp-server 2.启动tftp 五、准备pxelinx.0文件、引导文件、内核文件 1.准备pxelinux.0文件 2.准备引导文件、内核文件 六、配置dhcp …...

异地远程访问内网BUG管理系统【Cpolar内网穿透】

文章目录 前言1. 本地安装配置BUG管理系统2. 内网穿透2.1 安装cpolar内网穿透2.2 创建隧道映射本地服务3. 测试公网远程访问4. 配置固定二级子域名4.1 保留一个二级子域名5.1 配置二级子域名6. 使用固定二级子域名远程 前言 BUG管理软件,作为软件测试工程师的必备工具之一。在…...

论文笔记:一分类及其在大数据中的潜在应用综述

0 概述 论文&#xff1a;A literature review on one‑class classification and its potential applications in big data 发表&#xff1a;Journal of Big Data 在严重不平衡的数据集中&#xff0c;使用传统的二分类或多分类通常会导致对具有大量实例的类的偏见。在这种情况…...

下单时如何保证数据一致性?

原创 哪吒 哪吒编程 2023-09-07 08:03 发表于辽宁 收录于合集#Redis11个 &#xff08;给哪吒编程加星标&#xff0c;提高Java技能&#xff09; 大家好&#xff0c;我是哪吒。 在前几篇文章中&#xff0c;提到了Redis实现排行榜、Redis数据缓存策略&#xff0c;让我们对Redis…...

【C++ Core Guidelines解析】深入理解现代C++的特性和原理

文章目录 &#x1f468;‍⚖️《C Core Guidelines解析》的主要观点&#x1f468;‍&#x1f3eb;《C Core Guidelines解析》的主要内容&#x1f468;‍&#x1f4bb;作者介绍 &#x1f338;&#x1f338;&#x1f338;&#x1f337;&#x1f337;&#x1f337;&#x1f490;&a…...

Go语言高阶:Reflection反射与Files操作 详细示例教程

目录标题 一、Reflection反射1. What is reflection? 什么是反射2. Inspect a variable and find its type 检查变量并找到它的类型3. Reflect.Type and reflect.Value 反射类型和值4. Reflect.Kind 查看底层种类5. NumField() and Field() methods 字段数量和索引值方法6. In…...

谷歌seo技术流

很多外贸企业和独立站都想从Google获得免费的流量&#xff0c;也就是SEO流量&#xff0c;但是在做SEO的过程中&#xff0c;总会面临这样或那样的问题。米贸搜谷歌推广将这些问题总结如下&#xff1a; 既然SEO看起来似乎很难&#xff0c;但还是有很多电商公司愿意投资SEO&#x…...

ReactiveUI MVVM框架(1)-Collections

ReactiveUI MVVM框架&#xff08;1&#xff09;-Collections ReactiveUI使用动态数据&#xff08;DynamicData&#xff09;用于集合的操作。 当对动态数据集合进行更改时&#xff0c;会产生更改通知&#xff0c;通知表示为ChangeSet&#xff0c;里面包含了更改信息&#xff0…...

【微服务】五. Nacos服务注册

Nacos服务注册 5.1 Nacos服务分级存储模型Nacos服务分级存储模型&#xff1a;服务集群属性&#xff1a;总结&#xff1a; 5.2 根据集群负载均衡总结 5.3 Nacos服务实例的权重设置总结&#xff1a; 5.6 环境隔离namespace总结 5.7 Nacos和Eureka的对比总结 5.1 Nacos服务分级存储…...

Lnmp架构-Redis

网站&#xff1a;www.redis.cn redis 部署 make的时候需要gcc和make 如果在纯净的环境下需要执行此命令 [rootserver3 redis-6.2.4]# yum install make gcc -y 注释一下这几行 vim /etc/redis/6739.conf 2.Redis主从复制 设置 11 是master 12 13 是slave 在12 上 其他节…...

Python 二进制数据处理与转换

不得不说&#xff0c;Python能火是有原因的&#xff0c;物联网开发中常用的数据处理方式&#xff0c;Python都有内置的函数或方法&#xff0c;相当方便&#xff0c;官方文档见二进制序列类型&#xff0c;下面是一些示例代码 string Hello World! # 字符串转二进制数据 data …...

【LeetCode】297.二叉树的序列化与反序列化

题目 序列化是将一个数据结构或者对象转换为连续的比特位的操作&#xff0c;进而可以将转换后的数据存储在一个文件或者内存中&#xff0c;同时也可以通过网络传输到另一个计算机环境&#xff0c;采取相反方式重构得到原数据。 请设计一个算法来实现二叉树的序列化与反序列化…...

Java HashSet

HashSet 基于 HashMap 来实现的&#xff0c;是一个不允许有重复元素的集合。 HashSet 允许有 null 值。 HashSet 是无序的&#xff0c;即不会记录插入的顺序。 HashSet 不是线程安全的&#xff0c; 如果多个线程尝试同时修改 HashSet&#xff0c;则最终结果是不确定的。 您必…...

在iPhone上构建自定义数据采集完整指南

在iPhone上构建自定义数据采集工具可以帮助我们更好地满足特定需求&#xff0c;提高数据采集的灵活性和准确性。本文将为您提供一份完整的指南和示例代码&#xff0c;教您如何在iPhone上构建自定义数据采集工具。 自定义数据采集工具的核心组件 a、数据模型 数据模型是数据采…...

Android MediaRecorder录音

1. 简介 在android中录制音频有两种方式&#xff0c;MediaRecorder和AudioRecord。两者的区别如下&#xff1a; MediaRecorder 简单方便&#xff0c;不需要理会中间录制过程&#xff0c;结束录制后可以直接得到音频文件进行播放&#xff1b;录制的音频文件是经过压缩的&#…...

软件提示vcruntime140_1.dll丢失的解决方法,以及丢失的原因总结

在运行某些程序时&#xff0c;可能会出现“vcruntime140_1.dll 丢失”的错误提示。这是因为 vcruntime140_1.dll 是 Visual C Redistributable 的一部分&#xff0c;它通常被安装在 Windows 操作系统上。如果该文件丢失或无法找到&#xff0c;可能会导致程序无法正常运行。在我…...

Datax抽取mysql的bit类型数据

背景&#xff1a;使用datax抽取mysql的一张表&#xff0c;里面有两个bit类型的字段&#xff0c;抽取出来显示如下&#xff1a; 需要在抽取reader里面进行处理配置 最终生成的datax的json文件reader的配置会转换为具体的数值 最终查询效果&#xff1a;...

git 后悔药

前言 自上而下&#xff0c;撤销可以分为从远程库撤销&#xff0c;从本地库撤销&#xff0c;从暂存库撤销。 例子&#xff1a;代码已经提交了三个记录到远程库&#xff0c;分别对应了记录1&#xff0c;内容1&#xff0c;记录2&#xff0c;内容2&#xff0c;记录3&#xff0c;内…...

vue-cli搭建一个新项目及基础配置

vue-cli搭建一个新项目及基础配置 一、安装步骤二、main.js配置三、router下的index.js 一、安装步骤 1.安装node环境&#xff1a;下载地址&#xff1a;Node.js 2.安装脚手架&#xff1a;npm install -g vue/cli 3.创建vue项目&#xff1a;vue create 项目名 4.进入项目&…...

【C++】 C++11(右值引用,移动语义,bind,包装器,lambda,线程库)

文章目录 1. C11简介2. 统一的列表初始化2.1 &#xff5b;&#xff5d;初始化2.2 std::initializer_list 3. 声明3.1 auto3.2 decltype3.3 auto与decltype区别3.4 nullptr 4. 右值引用和移动语义4.1 左值引用和右值引用4.2 左值引用与右值引用比较4.3 右值引用使用场景和意义4.…...

附录1-爬虫的一些技巧

目录 1 寻找url与显示内容的关系 2 修改请求头 3 局部刷新 4 阅读返回信息 5 多尝试页面其他的使用方式 6 尝试不同类型参数 7 表单类型的post多用data发&#xff0c;接口类型的post多用json发 8 消除degger 9 你在浏览器上看到的html与你下载下来的html不一…...

【android12-linux-5.1】【ST芯片】【RK3588】【LSM6DSR】HAL移植

一、环境介绍 RK3588主板搭载Android12操作系统,内核是Linux5.10,使用ST的六轴传感器LSM6DSR芯片。 二、芯片介绍 LSM6DSR是一款加速度和角速度(陀螺仪)六轴传感器,还内置了一个温度传感器。该芯片可以选择I2C,SPI通讯,还有可编程终端,可以后置摄像头等设备,功能是很…...

DragGAN应运而生,未来在4G视频上都可能利用拖拽式编辑

原创 | 文 BFT机器人 2023年8月14日-15日&#xff0c;第七届GAIR全球人工智能与机器人大会在新加坡乌节大酒店成功举办。 在「AIGC 和生成式内容」分论坛上&#xff0c;南洋理工大学科学与工程学院助理教授潘新钢以《Interacitve Point-Dragging Manipulation of Visual Cont…...

【C++技能树】多态解析

Halo&#xff0c;这里是Ppeua。平时主要更新C&#xff0c;数据结构算法&#xff0c;Linux与ROS…感兴趣就关注我bua&#xff01; 文章目录 0.多态的概念0.1 多态的定义 1. 重写2.Final与Override3.抽象类4.多态中的内存分布.4.1虚表存在哪里? 5.多态调用原理5.1 动态绑定与静…...

【爬虫笔记】Python爬虫简单运用爬取代理IP

一、前言 近些年来&#xff0c;网络上的爬虫越来越多&#xff0c;很多网站都针对爬虫进行了限制&#xff0c;封禁了一些不规则的请求。为了实现正常的网络爬虫任务&#xff0c;爬虫常用代理IP来隐藏自己的真实IP&#xff0c;避免被服务器封禁。本文将介绍如何使用Python爬虫来…...

wordpress个人网站赚钱/seo内容优化心得

本篇下文首发于我的博客 说在前面 有时候我们将项目托管至github之后才发现,我们可能需要删除部分指定的目录或者文件,但是直接在.gitignore文件标注说明,推送到github之后,你会发现想要删除的目录仍然没有删除,所以此时我们需要使用git命令来进行删除. 删除指定目录或文件 先删…...

北京网站优化服务/杭州优化公司哪家好

随着互联网的发展&#xff0c;人们对页面的要求越来越高&#xff0c;不只是功能好用&#xff0c;而且还要颜值高。前端开发人员对于浏览器的滚动条并不陌生&#xff0c;当自带的一些滚动条无法满足我们的审美时&#xff0c;你知道如何用CSS修改浏览器滚动条的样式吗&#xff1f…...

私人做网站可靠吗/李江seo

2019独角兽企业重金招聘Python工程师标准>>> dim name dim fs, sname Inputbox("姓名") msgbox(name)set fs wscript.createobject("scripting.filesystemobject") fs为FSO实例if (fs.folderexists("c:\temp")) then 判断c:\te…...

企业门户网站 php/百度seo优化服务项目

一、前言 写这篇文章&#xff0c;是因为之前服务器有遇到过关于ssh服务的问题&#xff0c;sshd服务不稳定&#xff0c;出现断联等情况。影响日常操作。 今天就对该服务进行下总结 具体sshd服务的相关信息&#xff0c;可参考我之前文章&#xff1a; https://blog.csdn.net/xu71…...

做英剧网站的设计思路/百度问一问免费咨询

漂亮面料的设计 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 549 Accepted Submission(s): 206 Problem Description现在的CAD技术已经能够很方便地设计出漂亮的面料&#xff0c;如图&#xff08;b&#x…...

网络营销的网站建设/怎么策划一个营销方案

原标题&#xff1a;小程序日活超4亿&#xff0c;近10万商家开通直播&#xff0c;私域红利已来 &#xff01;9 月 9 日晚间消息&#xff0c;在 2020 腾讯全球数字生态大会微信专场上&#xff0c;微信团队透露&#xff0c;截止 2020 年8 月&#xff0c;小程序日活超过 4 亿&#…...