OpenCL编程指南-4.1OpenCL C编程

news2024/10/7 9:22:33

使用OpenCL C编写数据并行内核

OpenCL中的数据并行性表述为一个N维计算域,其中N=1、2或3。N-D域定义了可以并行执行的工作项的总数。下面通过一个简单的例子来了解如何用OpenCL C编写一个数据并行内核,将两个浮点数数组相加。这个代码的串行版本求和时需要通过一个for循环将两个数组中的各个元素相加:

void scalar_add (int n, const float *a, const float *b, float *result)
{
      int i;
      for (i = 0; i < n; i++)
      {
           result[i] = a[i] + b[i];
      }
}

使用OpenCL C的数据并行代码如下所示。

kernel void scalar_add(global const float *a, global const float *b, global float *result)
{
      int id = get_global_id(0);
      result[id] = a[id] + b[id];
}

scalar_add函数声明使用kernel限定符指示这是一个OpenCL C内核。需要说明的是,scalar_add内核只包括计算单个元素求和的代码,也就是内循环。N-D域是设置为n的1维域。对于n个工作项,要为每个工作项分别执行内核来生成数组a和b的和。为此,每个要执行内核的工作项需要知道要对数组a和 b中的哪个元素求和。对于各个工作项来说,这必须是唯一的值,要由N-D域(将内核入队等待执行时指定)得出。get_global_id(0)返回各个工作项的1维全局ID。

图4-1显示了如何使用get_global_id唯一标识执行内核的工作项列表中的一个工作项。
在这里插入图片描述
OpenCL C编程语言用来创建描述数据并行内核和任务的程序,这些内核和任务可以在一个或多个异构设备上执行,如 CPU、GPU和另外一些称为加速器的处理器(如DSP和 Cell Broad-band Engine (B.E.)处理器)。OpenCL程序类似于一个动态库,OpenCL 内核则类似于动态库的一个导出函数。应用程序可以直接从代码调用由动态库导出的函数。不过,应用程序不能直接调用OpenCL内核,只能将内核的执行放在一个为设备创建的命令队列中排队。内核与宿主机CPU上运行的应用代码异步执行。

OpenCL C基于ISO/IEC 9899:1999 C语言规范(简称为C99),并针对并行性对语言做了一些限制和特定扩展。

OpenCL C还为C99增加了以下特性:
1)矢量数据类型 很多OpenCL设备(如Intel SSE、面向POWER和Cell的AltiVec,以及ARM NEON)都支持矢量指令集。这个矢量指令集在C/C++代码中通过内置函数访问(其中一些可能特定于设备),或者利用设备特定的汇编指令访问。类似于C语言中使用标量类型,在OpenCL C中可以采用同样的方式使用矢量数据类型。基于这一点,开发人员可以更容易地编写矢量代码,因为可以对矢量和标量数据类型使用类似的操作符。这样还便于编写可移植的矢量代码,因为现在的OpenCL编译器会负责将OpenCL C中的矢量操作映射到设备上适当的矢量ISA。基于常规的内存访问以及更好地结合这些内存访问,矢量代码还有助于提高内存带宽。
2)地址空间限定符 诸如GPU等OpenCL设备实现了一个内存层次结构。地址空间限定符用来标识这个层次结构中的一个特定内存区域。
3)对语言的并行性补充 这包括对工作项和工作组的支持,还包括对工作组中工作项之间的同步提供支持。
4)图像 OpenCLC增加了图像和采样器数据类型,还增加了读、写图像的内置函数。
5)庞大的内置函数集合 如数学函数、整数函数、几何函数和关系函数。

标量数据类型

OpenCL C支持的C99标量数据类型如下1。与C不同,OpenCL C指定了整数和浮点数据类型的大小,也就是具体的位数。

bool                       这是一个条件数据类型,可以为truefalsetrue可以扩展为整数常量1,值false扩展为整数常量0

char                       有符号8位整数,2的补值
unsigned char uchar        无符号8位整数
short                      有符号16位整数,2的补值
unsigned short ushort      无符号16位整数
int                        有符号32位整数,2的补值
unsigned int uint          无符号32位整数
long                       有符号64位整数,2的补值
unsigned long ulong        无符号64位整数

float                      32位浮点数
                           float数据类型必须符合IEEE 754单精度存储格式

double                     64位浮点数
                           double 数据类型必须符合IEEE 754双精度存储格式
                           这是一个可选的格式,只有当设备支持双精度扩展(cl_khr_fp64)时才可用

half                       16位浮点数
                           half数据类型必须符合IEEE 754-2008半精度存储格式

size_t                     无符号整数类型,这是 sizeof操作符结果的类型
                           如果设备的地址空间为32位,这就是一个32位无符号整数;
                           如果设备的地址空间是64位,这就是个64位无符号整数

ptrdiff_t                  有符号整数类型,这是两个指针相减结果的类型
                           如果设备的地址空间为32位,这就是一个32位有符号整数;
                           如果设备的地址空间是64位,这就是一个64位有符号整数

intptr_t                   有符号整数类型,它有一个性质,任何指向void的合法指针都可以转换为这个类型,
                           然后还可以再转换回指向void的指针,其结果与原指针比较是相等的


uintptr_t                  无符号整数类型,它有一个性质,任何指向void 的合法指针都可以转换为这个类型,
                           然后还可以再转换回指向void的指针,其结果与原指针比较是相等的

void                       void类型构成值的一个空集
                           这是一个不完整的类型,而且不能补全
                           

half数据类型

half数据类型必须符合IEEE 754—2008。Half数有一个符号位、5个指数位和10个尾数位。符号、指数和尾数的解释与IEEE754浮点数的相应解释类似。指数偏差为15。half数据类型必须能表示有限标准数、非规格化数、无穷大和NaN(非数字)。half数据类型的非规格化数可能在使用内置函数vstore_half将一个float转换为half时生成,也可能在使用内置函数vload_half将一个half转换为float时生成,这些非规格化数不能刷新为0。

float转换为half时会适当地将尾数舍入为11位精度。Halffloat的转换则是无损的,所有half数都可以准确地表示为float值。

half数据类型只能用来声明指针指向一个包含half值的缓冲区。下面给出几个合法使用half数据类型的例子:

void bar(global half *p)
{
     ....
}

void foo(global half *pg, local half *pl)
{
     global half *ptr;
     int offset;
 
     ptr = pg + offset;
     bar(ptr);
}

下面是一个非法使用half类型的例子:

half a;
half a[100];

half *p;
a = *p; //not allowed. must use vload_half function

可以使用vload_halfvload_halfnvloada_halfn 以及 vstore_halfvstore_halfnvstorea_halfn函数分别完成对half指针的加载和存储。加载(load)函数从内存读取标量或矢量half值,将其转换为一个标量或矢量浮点值。存储(store)函数将一个标量或矢量浮点值作为输入,将它转换为一个half标量或矢量值(采用适当的舍入模式),并把这个half标量或矢量值写入内存。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/517743.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

在windows上通过QEMU快速上手RT-thread smart

参考链接 官方文档 资料下载 env-windows-v1.3.5.7z userapps 注意事项 通过QEMU仿真不同的平台&#xff0c;使用到的交叉编译工具也不一样&#xff0c;需要将相应工具的路径添加到系统PATH里&#xff1b;或者通过CMD定位到userapps&#xff0c;运行smart-env.bat xxx&…

【jvm系列-11】jvm性能调优篇---命令行工具的基本使用

JVM系列整体栏目 内容链接地址【一】初识虚拟机与java虚拟机https://blog.csdn.net/zhenghuishengq/article/details/129544460【二】jvm的类加载子系统以及jclasslib的基本使用https://blog.csdn.net/zhenghuishengq/article/details/129610963【三】运行时私有区域之虚拟机栈…

智能优化算法——下山单纯型算法

作者&#xff1a;非妃是公主 专栏&#xff1a;《智能优化算法》 博客地址&#xff1a;https://blog.csdn.net/myf_666 个性签&#xff1a;顺境不惰&#xff0c;逆境不馁&#xff0c;以心制境&#xff0c;万事可成。——曾国藩 文章目录 专栏推荐序一、算法流程1. 反射2. 膨胀…

马哈鱼SQLFLow数据流生成介绍

马哈鱼数据血缘分析器是当前最流行的数据血缘关系(data lineage)管理工具之一&#xff0c;它是一种通过分析SQL脚本来自动发现数据流向的工具。它通过生成一个简洁的图表来显示数据仓库中表/视图和列之间的数据流。支持超过20种流行的数据库&#xff0c;包括 bigquery, couchba…

项目风险的4种应对策略及实施条件

面对威胁或可能给项目带来消极影响的风险&#xff0c;我们一般采用规避、转移、缓解和接受的应对策略。 一、风险规避 风险规避策略是指项目团队采取行动来消除威胁&#xff0c;或保护项目免受风险影响的应对策略&#xff0c;通常包括改变项目管理计划&#xff0c;以完全消除威…

super_数学知识(质数筛选和约数学习)lesson08易错题记录

文章目录 回文质数第n小的质数素数个数 回文质数 先上代码 #include<iostream> #include<vector>//创建动态数组需要的头文件 #include<cstring>//使用memset需要的头文件 using namespace std; vector<int> q; bool arr[10000005]; //埃氏筛法找出所…

详解软件开发的标准过程(生命周期):跟着标准搞,设计没烦恼

目录 一.软件开发的生命周期总括 二.项目架构分类 C/S架构 B/S架构 三.详解软件需求 需求分类 需求获取 需求分析 四.详解面向对象分析&#xff08;OOA&#xff09; 概念理解&#xff1a; 统⼀建模语⾔UML UML的重要组成部分&#xff1a; ⽤例图的元素 识别参与者…

怎么搭建个人小型渲染农场?搭建渲染农场配置

渲染农场是众多机器组成的渲染集群&#xff0c;通常用来渲染你的单帧效果图或动画项目&#xff0c;我们借助渲染农场的力量&#xff0c;可以满足3D项目交期时间迫在眉睫的需求&#xff0c;当你试着在自己的机器上渲染一个复杂的动画项目时&#xff0c;可能需要几十小时的等待时…

gdb与symbol符号表文件的调试

目录 1&#xff0c;剥离命令 2&#xff0c;gdbdebug 文件的调试 今天在调试程序的时候发现&#xff0c;在测试部测试的程序都是剥离了符号表的&#xff0c;导致用gdb无法调试&#xff0c;只有找到符号表文件才能继续gdb调试&#xff0c;好在符号表文件是和程序一起发布的。之…

浅谈作为程序员如何写好文档:了解读者

我作为从一名懵懂的实习生转变为工程师的工作经历中&#xff0c;伴随着技术经验的成长&#xff0c;也逐渐意识到了编写文档是知识和经验传递给其他人的最有效方式。通过文档&#xff0c;可以分享我的技术知识和最佳实践&#xff0c;使其他人更好地理解我的工作。在这里&#xf…

Postgres : 创建schema、创建表空间与指定用户权限

1. 创建新的Schema 要创建 PostgreSQL 中的一个新的 schema&#xff0c;并创建一个只有该 schema 权限的新用户&#xff0c;请按照以下步骤操作&#xff1a; &#xff08;1&#xff09;打开 PostgreSQL 客户端并连接到数据库服务器。 &#xff08;2&#xff09;创建一个新的…

如何在Oracle存储过程发生异常时获取out类型参数的值

Oracle存储过程关于在出现&#xff08;自定义/自带&#xff09;异常下out类型参数的获取问题的分析 ✈️ 场景: 有一些关于金额和时间的精确且量大的计算需要在存储过程中完成。存储过程中有一些自定义的异常。并且将在RAISE前通过out类型的参数将详细的异常原因返回。 但是在…

商业智能BI分析报表很慢是什么原因?应该如何优化?

当下&#xff0c;数据计算已成为了分析工作中必不可少的高频次操作之一&#xff0c;而且在大数据的发展背景下&#xff0c;应用性能往往关系着项目的成败&#xff0c;成为了大家最为关注的产品技术参数。那么我们先来分析一下BI分析表计算很慢的原因是什么&#xff0c;再对症下…

Microsoft Dynamics 365 Business Central 生产订单扣料的几种方法

学习目标&#xff1a; 掌握生产订单扣料的几种方法 学习内容&#xff1a; Forward flush by routing operation&#xff08;通过工序&#xff1a;向前扣料&#xff09;Backward flush by routing operation&#xff08;通过工序&#xff1a;向后扣料&#xff09;Forward flus…

Java-Redis持久化之RDB操作

Java-Redis持久化之RDB操作 1.为什么redis需要持久化&#xff1f;2.什么是RDB操作?3.请你用自己的话讲下RDB的过程?4.如何恢复rdb文件? 1.为什么redis需要持久化&#xff1f; Redis是内存数据库&#xff0c;如果不将内存数据库保存到磁盘&#xff0c;那么服务器进程退出&am…

匿名对象的特性和使用场景你知道吗?

目录 一、匿名对象的概念 二、单参数和多参数构造场景的匿名对象 ①只有一个参数的构造函数 ②多个参数的构造函数 三、使用匿名对象作为函数的参数的缺省值 四、只为调用类中的一个函数时 五、匿名对象的特性 1、匿名对象的生命周期只有一行 2、匿名对象具有常性 3、当匿…

今天去面一个点工,HR要我会数据库,Linux还有Python,这合理吗?

软件测试出路在哪&#xff1f; 业务编程&#xff01;&#xff01; 1、软件测试的变化趋势 变化趋势1&#xff1a; 功能测试是核心&#xff0c;但是价值降低 目前测试这个行业&#xff0c;还是有大量的点工。但是行业的进步&#xff0c;技术的创新&#xff0c;导致了企业的需求…

不用下载的网页版Axure在这里

作为一名产品经理&#xff0c;你一定需要一款能够帮助你更好更快地制作原型&#xff0c;更方便地和团队协作的软件。网页版Axure工具替代即时设计无需下载激活&#xff0c;就可免费使用。那么&#xff0c;Axure网页版工具替代即时设计是如何进行的呢&#xff1f; 首先&#xf…

【数据结构】双向带头循环链表

文章目录 一、什么是带头双向循环链表二、带头双向循环链表的实现&#xff08;一&#xff09;链表中结构体的声明&#xff08;二&#xff09;头节点的创建&#xff08;链表的初始化&#xff09;&#xff08;三&#xff09;新节点的创建&#xff08;四&#xff09;链表的尾插&am…

( 位运算 ) 231. 2 的幂 ——【Leetcode每日一题】

❓231. 2 的幂 难度&#xff1a;简单 给你一个整数 n&#xff0c;请你判断该整数是否是 2 的幂次方。如果是&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 如果存在一个整数 x 使得 n 2 x n 2^x n2x &#xff0c;则认为 n 是 2 的幂次方。 示例 1&…