CUDA从入门到放弃(十三):C++语言扩展 C++ Language Extensions

news2024/11/26 8:21:17

CUDA从入门到放弃(十三):C++语言扩展 C++ Language Extensions

1 Function Execution Space Specifiers 函数执行空间指定符

这些指定符定义函数是在主机还是设备上执行,以及它们是否可以跨平台调用。

1-1 __global__

__global__指定函数为内核,可在设备上执行,也可从主机或(计算能力5.0以上设备)设备上调用。必须有void返回类型,调用是异步的。

1-2 device

device 指定函数只在设备上执行,只能从设备调用。不能与__global__ 一起使用。

1-3 host

host__指定函数在主机上执行,只能从主机调用。等价于不使用任何执行空间指定符,函数仅编译为主机代码。不能与__global 一起使用,但可以与__device__ 一起使用,此时函数将同时编译为主机和设备代码。使用__CUDA_ARCH__ 宏可以区分主机和设备代码路径。

__host__ __device__ func()
{
	#if __CUDA_ARCH__ >= 800
   	// Device code path for compute capability 8.x
	#elif __CUDA_ARCH__ >= 700
   	// Device code path for compute capability 7.x
	#elif __CUDA_ARCH__ >= 600
   	// Device code path for compute capability 6.x
	#elif __CUDA_ARCH__ >= 500
   	// Device code path for compute capability 5.x
	#elif !defined(__CUDA_ARCH__)
   	// Host code path
	#endif
}

1-4 Undefined behavior

跨执行空间调用时,若__CUDA_ARCH__已定义,从__global__、device__或__host __device__函数中调用__host__函数,或__CUDA_ARCH__未定义时,从__host__函数中调用__device__函数,行为是未定义的。

1-5 noinline and forceinline

编译器会适当内联__device__函数。__noinline__修饰符提示编译器尽量避免内联,__forceinline__修饰符强制内联。两者不可同时使用,且不适用于内联函数。

1-6 inline_hint

inline_hint__修饰符促进编译器更积极内联,不同于__forceinline,它不保证函数一定会内联。使用LTO时,有助于改善跨模块内联。它不与__noinline__或__forceinline__修饰符共用。

2 变量内存空间指定符 Variable Memory Space Specifiers

变量内存空间指定符决定了变量在设备上的存储位置。

变量若未使用__device__、__shared__和__constant__指定符,通常放在寄存器中。但编译器可能将其置于本地内存,这可能影响性能。

2-1 device

__device__指定符表示变量驻留在设备上。它可以与其他指定符结合,进一步定义变量的内存空间。若无其他指定符,则变量位于全局内存,具有CUDA上下文的生命周期,每设备一个独立对象,可从网格内所有线程和主机访问。

2-2 constant

constant(可与__device__结合)指定变量驻留在常量内存,同样具有CUDA上下文的生命周期,每设备一个独立对象,可从网格内所有线程和主机访问。

2-3 shared

__shared__内存空间指定符(可与__device__一起使用)声明一个变量,该变量位于线程块的共享内存中,其生命周期与线程块相同,每个线程块有独立对象,仅可从该线程块内的线程访问,地址不固定。

在声明共享内存中的变量为外部数组时,如:

extern __shared__ float shared[];

数组的大小在启动时确定.

2-4 grid_constant

在计算架构7.0及以上的环境中,__grid_constant__注解用于标记const限定的非引用类型__global__函数参数。这些参数具有网格的生命周期,私属于网格,每个网格有一个独立的对象,且是只读的。编译器不会为这些参数创建线程本地内存中的副本,而是使用参数本身的地址,这有助于提升性能。

__device__ void unknown_function(S const&);  
__global__ void kernel(const __grid_constant__ S s) {  
   s.x += threadIdx.x;  // 未定义行为:尝试修改只读内存  
  
   // 编译器将不会为每个线程创建"s"的线程本地副本:  
   unknown_function(s);  
}

2-5 managed

__managed__是一个内存空间指定符,用于声明在主机和设备上均可访问的变量。这些变量与CUDA上下文同生命周期,主机访问时通过页锁定内存管理,设备访问时驻留在设备内存中。使用__managed__可以简化数据复制的代码,但程序员需注意潜在的同步和数据竞争问题。

2-6 restrict

nvcc支持使用__restrict__关键字来声明受限指针,这是C99中引入的特性,旨在解决C类语言中的别名问题,从而优化代码。在C中,指针可能指向相同的内存位置,这限制了编译器进行诸如重排序和公共子表达式消除等优化。通过声明受限指针,程序员告诉编译器这些指针不会指向相同位置,从而允许编译器进行更多优化。例如,在函数foo中,通过为参数a、b和c添加__restrict__修饰符,编译器可以更安全地优化指令,减少计算冗余,同时保持程序的正确性。

void foo(const float* __restrict__ a,  
         const float* __restrict__ b,  
         float* __restrict__ c)  
{  
    float t0 = a[0];  
    float t1 = b[0];  
    float t2 = t0 * t1;  
    float t3 = a[1];  
    c[0] = t2;  
    c[1] = t2;  
    c[4] = t2;  
    c[2] = t2 * t3;  
    c[3] = t0 * t3;  
    c[5] = t1;  
    ...  
}

为了让编译器优化器获益,所有指针参数必须声明为受限。使用__restrict__后,编译器能自由优化指令,减少内存访问和计算,但可能增加寄存器压力。在CUDA代码中,寄存器压力是关键问题,因此使用受限指针可能因减少占用率而降低性能。

3. 内置向量类型 Built-in Vector Types

3-1. char, short, int, long, longlong, float, double

这些是基于基本整数和浮点类型派生的向量类型。它们是结构体,其第1、第2、第3和第4个组件分别可以通过字段x、y、z和w来访问。它们都带有形式为make_<类型名>的构造函数函数;例如,

int2 make_int2(int x, int y);

这个函数会创建一个值为(x, y)的int2类型的向量。

在这里插入图片描述

3-2. dim3

这种类型是基于uint3的整数向量类型,用于指定维度。在定义dim3类型的变量时,未指定的任何组件都会初始化为1。

4 内置变量 Built-in Variables

内置变量用于指定网格和块的维度以及块和线程的索引。它们仅在设备上执行的函数内部有效。

4-1 gridDim

这个变量是dim3类型(参见dim3),包含网格的维度。

4-2 blockIdx

这个变量是uint3类型(参见char, short, int, long, longlong, float, double),包含网格内的块索引。

4-3 blockDim

这个变量是dim3类型(参见dim3),包含块的维度。

4-4 threadIdx

这个变量是uint3类型(参见char, short, int, long, longlong, float, double),包含块内的线程索引。

4-5 warpSize

这个变量是int类型,包含warp中的线程数。

5 内存屏障函数 Memory Fence Functions

CUDA编程模型使用弱序内存模型,即CUDA线程写入数据的顺序并不一定是其他线程观察到数据写入的顺序。两个线程无同步地读写同一内存位置会导致未定义行为。

内存屏障函数用于确保内存访问的顺序一致性,不受访问的内存空间类型影响。

void __threadfence_block() 

确保同一块内的线程能观察到调用前后的内存操作顺序。

void __threadfence() 

确保设备内所有线程观察到调用前后的内存操作顺序。

void __threadfence_system() 

确保设备、主机以及对等设备的所有线程观察到调用前后的内存操作顺序。

内存屏障函数仅控制线程的内存操作顺序,不保证对其他线程可见。

6 同步函数 Synchronization Functions

void __syncthreads(); 

同步同一线程块内所有线程,确保所有线程到达该点前对全局和共享内存的访问对所有线程可见。

int __syncthreads_count(int predicate); 

同步线程并返回谓词为真的线程数。

int __syncthreads_and(int predicate); 

同步线程并仅当所有线程谓词为真时返回非零。

int __syncthreads_or(int predicate); 

同步线程并仅当任意线程谓词为真时返回非零。

void __syncwarp(unsigned mask=0xffffffff); 

使线程等待,直到指定掩码中的所有warp通道执行该函数后继续执行,确保内存顺序。

参考资料
1 CUDA编程入门
2 CUDA编程入门极简教程
3 CUDA C++ Programming Guide
4 CUDA C++ Best Practices Guide
5 NVIDIA CUDA初级教程视频
6 CUDA专家手册 [GPU编程权威指南]
7 CUDA并行程序设计:GPU编程指南
8 CUDA C编程权威指南

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

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

相关文章

健身房预约管理系统(源码+文档)

健身房预约管理系统&#xff08;小程序、ios、安卓都可部署&#xff09; 文件包含内容程序简要说明含有功能&#xff1a;项目截图客户端首页我的预约登录教练预约时间我的注册页个人资料课程预约课程预约 管理端订单管理团课管理教练管理分类管理用户管理 文件包含内容 1、搭建…

[数据结构]排序

本篇主要是对常见排序的分类和一些排序的详解 一、插入排序 1.直接插入排序 // 直接插入排序函数 void insertionSort(int arr[], int n) {int i, key, j;for (i 1; i < n; i) {key arr[i]; // 取出待排序的元素j i - 1;// 将大于key的元素向后移动一位while (j > 0…

6.5 Batch Normalization

在训练神经网络时&#xff0c;往往需要标准化&#xff08;normalization&#xff09;输入数据&#xff0c;使得网络的训练更加快速和有效。 然而SGD&#xff08;随机梯度下降&#xff09;等学习算法会在训练中不断改变网络的参数&#xff0c;隐藏层的激活值的分布会因此发生变…

MySQL故障排查与生产环境优化

一、MySQL单实例常见故障 1.逻辑架构图 MySQL逻辑架构图客户端和连接服务核心服务功能存储引擎层数据存储层 2.故障一 故障现象 ERROR 2002 (HY000): Cant connect to local MySQL server through socket/data/mysql/mysql.sock(2) 问题分析 数据库未启动或者数据库端口…

淘宝优惠券去哪里领取隐藏内部券?

淘宝优惠券去哪里领取隐藏内部券&#xff1f; 1、手机安装「草柴」APP&#xff0c;打开手机淘宝挑选要购买的商品&#xff0c;并点击分享复制链接&#xff1b; 2、将复制的商品链接&#xff0c;粘贴到草柴APP&#xff0c;并点击立即查询该商品的优惠券和约返利&#xff1b; 3、…

java题目15:从键盘输入n个数,求这n个数中的最大数与最小数并输出(MaxAndMin15)

每日小语 你是否有资格摆脱身上的枷锁呢&#xff1f;有许多人一旦获得解放&#xff0c;他的最后一点价值也就会跟着丧失。 ——尼采 自己敲写 它不按我想的来。。。 //从键盘输入n个数&#xff0c;求这n个数中的最大数与最小数并输出 import java.util.Scanner; public clas…

软件测评师教程之软件测试基础

&#x1f525; 交流讨论&#xff1a;欢迎加入我们一起学习&#xff01; &#x1f525; 资源分享&#xff1a;耗时200小时精选的「软件测试」资料包 &#x1f525; 教程推荐&#xff1a;火遍全网的《软件测试》教程 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1…

Mysql数据库:故障分析与配置优化

目录 前言 一、Mysql逻辑架构图 二、Mysql单实例常见故障 1、无法通过套接字连接到本地MySQL服务器 2、用户rootlocalhost访问被拒绝 3、远程连接数据库时连接很慢 4、无法打开以MYI结尾的索引文件 5、超出最大连接错误数量限制 6、连接过多 7、配置文件/etc/my.cnf权…

全栈开发与测试定向培养班

Python全栈开发与测试 什么是软件测试&#xff1f; 对于测试行业来说&#xff0c;行业普遍会把职位分为测试工程师和测试开发工程师两个岗位。软件测试工程师就是常规意义上了解到的功能测试岗位&#xff0c;以功能测试为主,会有少量的自动化测试。测试能力要求&#xff1a;熟…

键盘输入与屏幕输出——单个字符的输入和输出

目录 字符常量 字符型变量 单个字符的输入输出 两种输入输出方法的比较 字符常量 字符常量是用单引号括起来的一个符号 *’3’表示一个数字字符&#xff0c;而3则表示一个整数数值 转义字符&#xff08;Escape Character&#xff09; *一些特殊字符&#xff08;无法从键盘…

Dimitra:基于区块链、AI 等前沿技术重塑传统农业

根据 2023 年联合国粮食及农业组织&#xff08;FAO&#xff09;、国际农业发展基金&#xff08;IFAD&#xff09;等组织联合发布的《世界粮食安全和营养状况》报告显示&#xff0c;目前全球约有 7.35 亿饥饿人口&#xff0c;远高于 2019 年的 6.13 亿&#xff0c;这意味着农业仍…

【Linux C | 多线程编程】线程的连接、分离,资源销毁情况

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; ⏰发布时间⏰&#xff1a;2024-04-01 1…

讲解pwngdb的用法,以csapp的bomb lab phase_1为例

参考资料 Guide to Faster, Less Frustrating Debugging 什么情况下会使用gbd 需要逆向ELF文件时(掌握gdb的使用&#xff0c;是二进制安全的基本功)开发程序时&#xff0c;程序执行结果不符合预期 动态调试ELF文件可以使用另外一种方法&#xff1a;IDA的远程linux动态调试。个…

探索 Redis 数据库:一款高性能的内存键值存储系统

目录 引言 一、非关系型数据库 &#xff08;一&#xff09;什么是非关系型数据库 &#xff08;二&#xff09;非关系型数据库的主要特征 &#xff08;三&#xff09;关系数据库与非关系型数据库的区别 二、Redis 简介 &#xff08;一&#xff09;基本信息 &#xff08;…

栈————顺序栈和链式栈

目录 栈 顺序栈 1、初始化顺序栈 2、判栈空 3、进栈 4、出栈 5、读栈顶元素 6、遍历 链式栈 1、初始化链式栈 2、断链式栈是否为空判 3、入栈(插入) ​编辑​编辑 4、出栈(删除) 5、读取栈顶元素 6、输出链式栈中各个节点的值&#xff08;遍历&#xff09; 栈 …

LeetCode-240. 搜索二维矩阵 II【数组 二分查找 分治 矩阵】

LeetCode-240. 搜索二维矩阵 II【数组 二分查找 分治 矩阵】 题目描述&#xff1a;解题思路一&#xff1a;从左下角或者右上角元素出发&#xff0c;来寻找target。解题思路二&#xff1a;右上角元素&#xff0c;代码解题思路三&#xff1a;暴力也能过解题思路四&#xff1a;二分…

【小呆的力学笔记】弹塑性力学的初步认知六:后继屈服条件

文章目录 4. 后继屈服条件4.1 后继屈服条件4.2 强化模型4.2.1 等向强化模型4.2.2 随动强化模型4.2.3 两种强化模型的讨论 4. 后继屈服条件 4.1 后继屈服条件 上一章节的屈服条件是在当材料未经受任何塑性变形时且在载荷作用下材料第一次进入屈服应该满足的条件&#xff08;也…

Vscode + PlatformIO + Arduino 搭建EPS32开发环境

Vscode PlatformIO Arduino 搭建EPS32开发环境 文章目录 Vscode PlatformIO Arduino 搭建EPS32开发环境1. Vscode插件安装2. 使用PlatformIO新建工程3.工程文件的基本结构4.一个基本的测试用例Reference 1. Vscode插件安装 如何下载vscode这里不再赘述&#xff0c;完成基本…

LeetCode-热题100:160. 相交链表

给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点&#xff0c;返回 null 。 图示两个链表在节点 c1 开始相交&#xff1a; 题目数据 保证 整个链式结构中不存在环。 注意&#xff0c;函数返回结果后&…

异常,Lambda表达式

文章目录 异常介绍存在形式程序中异常发生后的第一反应体系JVM的默认处理方案处理方式声明 throws概述格式抛出 throw格式注意意义 throws和throw的区别 捕获 try,catch介绍格式执行方式多异常捕获处理意义 如何选择用哪个 Throwable类介绍常用方法 自定义异常概述实现步骤范例…