CUDA原子操作
这节主要涉及到一个多线程情况下存在的数据竞争问题 -- 多个线程同时访问共享数据时,由于没有正确的同步机制,导致数据出现不一致的情况。
C/C++ 多线程中,可以通过互斥锁(mutex)、原子操作(atomic,C++11 也提供了原子操作库,如std::atomic,用于实现原子加法、原子赋值等操作)、线程局部变量(C++11提供了thread_local,它为每个线程分配了一份独立的内存,使得不同线程之间的局部变量互不干扰。这样可以避免多个线程访问同一共享数据时的数据竞争问题)以及使用同步代码块(using)、全局变量等措施来避免多线程操作
由于CUDA采用单指令多线程(Single-Instruction Multiple-Thread,SIMT)来管理和执行 GPU 上的众多线程,因此在操作数据时,也会存在数据竞争等问题,而在CUDA中避免数据竞争的方法主要包括使用原子操作和适当的索引计算。
原子操作可以确保在多线程环境下对共享变量进行原子的读写操作,从而避免数据竞争。
利用线程索引计算可以使得每个线程操作不同的数据元素,避免竞争
上代码:
__global__ void increment_naive(int *g)
{
int idx = threadIdx.x + blockIdx.x * blockDim.x;
idx = idx % ARRAYSIZE;
// g[idx] = g[idx] + 1;
printf("before %d:%d\n", idx, g[idx]);
atomicAdd(& g[idx], 1);
printf("after %d:%d\n", idx, g[idx]);
}
从主机代码中将数据拷贝到设备端,默认都是放在设备的全局内存中(也就是global memory中),在运行核函数时从全局内存中读数据、运算、写入全局内存
- 首先多个线程会同时从全局内存中取出g[idx]的数据,
- 运算,
g[idx] = g[idx] + 1;
虽然此处计算了,也写入了对应的g[idx]中,但是其他线程并没有拿到这个线程计算的的结果,他们用的数据还是最开始的原始数据,导致最后计算出错
atomicAdd(& g[idx], 1);
该函数为CUDA提供的原子函数接口,该接口详细描述如下:
int atomicAdd(int* address, int val);
unsigned int atomicAdd(unsigned int* address,
unsigned int val);
unsigned long long int atomicAdd(unsigned long long int* address,
unsigned long long int val);
float atomicAdd(float* address, float val);
double atomicAdd(double* address, double val);
__half2 atomicAdd(__half2 *address, __half2 val);
__half atomicAdd(__half *address, __half val);
__nv_bfloat162 atomicAdd(__nv_bfloat162 *address, __nv_bfloat162 val);
__nv_bfloat16 atomicAdd(__nv_bfloat16 *address, __nv_bfloat16 val);
上面是 device-wide atomicAdd 不同数据类型的定义,表示从第一个参数 address 指针指向的内存地址(可以是全局内存或共享内存)中读取16位、32位或64位数据(记做旧值 old),与第二个参数val 做一个加法计算,(old + val)
,然后将求和结果写回到 address 指针指向的内存地址中,并返回未做计算前的旧值 old。这三个操作在一个原子事务中执行。
- 32位 floating-point 浮点版本的 atomicAdd() 仅由计算能力 2.x 及更高版本的设备支持。
- 64位 floating-point 浮点版本的 atomicAdd()只被具有计算能力 6.x 及更高版本的设备支持。
- 32位 __half2 浮点版本的 atomicAdd() 只被具有计算能力 6.x 及更高版本的设备支持。对于两个__half 或__nv_bfloat16 元素,分别保证 __half2 或 __nv_bfloat162 添加操作的原子性;整个__half2 或 __nv_bfloat162 不能保证作为单个32位访问是原子的。
- 16位 __half 浮点版本的 atomicAdd() 仅由计算能力为 7.x 及更高版本的设备支持。
- 16位 __nv_bfloat16 浮点版本的 atomicAdd() 仅由计算能力为 8.x 及更高版本的设备支持。
CUDA原子操作的更多相关文章
- 5.1 CUDA atomic原子操作
和许多多线程并行问题一样,CUDA也存在互斥访问的问题,即当一个线程改变变量X,而另外一个线程在读取变量X的值,执行原子操作类似于有一个自旋锁,只有等X的变量在改变完成之后,才能执行读操作,这样可以保 ...
- 【CUDA并行程序设计系列(1)】GPU技术简介
http://www.cnblogs.com/5long/p/cuda-parallel-programming-1.html 本系列目录: [CUDA并行程序设计系列(1)]GPU技术简介 [CUD ...
- 《GPU高性能编程CUDA实战》附录一 高级原子操作
▶ 本章介绍了手动实现原子操作.重构了第五章向量点积的过程.核心是通过定义结构Lock及其运算,实现锁定,读写,解锁的过程. ● 章节代码 #include <stdio.h> #incl ...
- CUDA atomic原子操作
CUDA的原子操作可以理解为对一个变量进行"读取-修改-写入"这三个操作的一个最小单位的执行过程,这个执行过程不能够再分解为更小的部分,在它执行过程中,不允许其他并行线程对该变量进 ...
- CUDA: 原子操作
1.1以上计算功能集支持全局内存上的原子操作, 1.2以上支持共享内存上的原子操作. atomicAdd(add,y)将生成一个原子的操作序列,这个操作序列包括读取地址addr处的值,将y增加到这个值 ...
- CUDA 进阶学习
CUDA基本概念 CUDA网格限制 1.2CPU和GPU的设计区别 2.1CUDA-Thread 2.2CUDA-Memory(存储)和bank-conflict 2.3CUDA矩阵乘法 3.1 全局 ...
- CUDA从入门到精通
http://blog.csdn.net/augusdi/article/details/12833235 CUDA从入门到精通(零):写在前面 在老板的要求下.本博主从2012年上高性能计算课程開始 ...
- 5.2 CUDA Histogram直方图
什么是Histogramming Histogramming是一种从大的数据集中提取典型特征和模式的方式. 在统计学中,直方图(英语:Histogram)是一种对数据分布情况的图形表示,是一种二维统计 ...
- CUDA C Best Practices Guide 在线教程学习笔记 Part 1
0. APOD过程 ● 评估.分析代码运行时间的组成,对瓶颈进行并行化设计.了解需求和约束条件,确定应用程序的加速性能改善的上限. ● 并行化.根据原来的代码,采用一些手段进行并行化,例如使用现有库, ...
- CUDA C
一.CUDA结构 硬件:GPU(Graphics Processing Unit) SM(Streaming Multiprocessor) SP(Streaming Processor) ...
随机推荐
- Go实现动态开点线段树
1.线段树介绍 线段树是一种用于高效处理区间查询和区间更新的数据结构,当我们需要解决一个频繁更新区间值的问题的时候,就可以采用线段树的结构进行解决.线段树的核心思想是将区间分为多个子区间进行管理,越往 ...
- Idea - 关于mybatis的插件
idea中配置的mybatis的mapper类和xml文件的图标怎么自动变为mybatis的logo?需要安装什么插件,怎么安装? 在 IntelliJ IDEA 中,要使 MyBatis 的 ...
- 【Python】批量提取Fibersim xml文件中的节点网格数据
程序功能: 输入需求: fibersim导出的ply 的xml文件,可以很多个也没问题.但名字要有规律,不然没法循环读写.比如我自己用的就是x1.xml.x2.xml.Y1.xml......的文件名 ...
- 【ABAQUS模态动力学】Material-Damping 对模态分析的影响
先说结论,执行Frequency Step (特征值提取)时定义材料行为中的Damping 行为,对结果没有影响. 1. abaqus calculation compare 1.1 ANALYSIS ...
- 基于近红外与可见光双目摄像头的人脸识别与活体检测,文末附Demo
基于近红外与可见光双目摄像头的活体人脸检测原理 人脸活体检测(Face Anti-Spoofing)是人脸识别系统中的重要一环,它负责验证捕捉到的人脸是否为真实活体,以抵御各种伪造攻击,如彩色纸张打印 ...
- [tldr] 配置windows terminal使用git bash
windows terminal默认使用power shell作为shell,但是power shell不好用,还是习惯linux的命令行行为. 参考Windows Terminal 配置 Git B ...
- Oracle VM VirtualBox虚拟机安装Centos
virtualBOx 6.x.x版本跟 virtualBOx 5.x.x 界面已经不一样,但安装步骤还是一样的 镜像下载可以使用下面帖子中的,网易镜像或者阿里云镜像,选取适合自己的镜像 开源镜像站,v ...
- OpenGL ES与GLSL ES各版本对应说明
OpenGL ES 3.2 OpenGL ES 3.2 and OpenGL ES Shading Language 3.20 OpenGL ES 3.1 OpenGL ES 3.1 and Open ...
- apisix~hmac-auth插件的使用
hmac-auth插件需要和 Consumer 一起使用,API 的使用者必须将密匙添加到请求头中以验证其请求,下面介绍它的主要用法 参数 algorithm 算法 默认hmac-sha256 [&q ...
- Win10禁用UWP
Win10禁用UWP, HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\WindowsStore DisableStoreApps REG_DWORD 0 ...