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) ...
随机推荐
- vue element-ui resetForm()表单重置的问题
- 面试题55 - II. 平衡二叉树
地址:https://leetcode-cn.com/problems/ping-heng-er-cha-shu-lcof/ <?php /** 输入一棵二叉树的根节点,判断该树是不是平衡二叉树 ...
- c# 使用 Read 读取数据块
class Program { static void Main(string[] args) { Stream s = new MemoryStream(); for (int i = 0; i & ...
- redmine 127访问成功,其他机器不能访问
添加防火墙 入站规则
- 基于近红外与可见光双目摄像头的活体人脸检测,文末附Demo
基于近红外与可见光双目摄像头的活体人脸检测原理 人脸活体检测(Face Anti-Spoofing)是人脸识别系统中的重要一环,它负责验证捕捉到的人脸是否为真实活体,以抵御各种伪造攻击,如彩色纸张打印 ...
- 【P1】Verilog部件级实验/有限状态机
课上 再次体验大心脏 T1 奇偶校验 for循环数1的个数判断奇偶/异或缩减运算符判断奇偶,然后根据check的奇偶要求调整最高位 bug1 !注意优先级:位运算 低于 比较运算. cnt & ...
- Ollama——大语言模型本地部署的极速利器
1.概述 Ollama 是一款开源跨平台大模型工具,主要用于在本地便捷部署和运行大型语言模型(LLM),核心目标是降低用户使用大模型的门槛,同时保障数据隐私.核心功能与特点如下: (1)本地部署,隐私 ...
- go ceph s3文件管理
导入依赖 go get gopkg.in/amz.v1/aws go get gopkg.in/amz.v1/s3 创建用户 在初始化连接之前,我们需要创建一个用户得到accessKey和secret ...
- go mod 安装bee 报错
报错信息 go: github.com/beego/bee imports github.com/beego/bee/cmd imports github.com/beego/bee/cmd/comm ...
- python-argparse用法简介
1. argparse介绍 argparse是Python标准库中用于解析命令行参数的模块.它提供了一种简洁而灵活的方式来处理命令行参数,包括选项(可选参数)和位置参数(必需参数) 2. argpar ...