CUDA cooperative_groups grid_group测试

news2024/9/29 15:32:47

CUDA cooperative_groups grid_group测试

  • 一.测试描述及小结
    • 1.任务描述
    • 2.输出
    • 3.小结
  • 二.复现步骤
  • 三.grid_group.sync 代码对照
    • 1.CUDA C
    • 2.PTX
    • 3.SASS

CUDA Cooperative Groups是CUDA编程模型中引入的一组高级特性,提供了更灵活的线程组织和同步机制
通过Cooperative Groups,开发者可以在不同层次上组织线程,并执行更高效的并行操作
grid_group.sync 可用于整个grid同步

一.测试描述及小结

1.任务描述

  • 一个thread block只有2个线程,4个thread block
  • 用cooperative_groups的grid_group做所有线程的同步
  • 因为grid_group没有广播功能,于是采用tid=0 的sm时钟做全局时钟
  • 在Kernel中记录当前当前线程对应的smid、全局时钟、当前时钟

2.输出

tid:00 smid:00 local_ts:477113991510614 global_ts:477113991321194
tid:01 smid:00 local_ts:477113991510614 global_ts:477113991321194
tid:06 smid:06 local_ts:477113991510702 global_ts:477113991321194
tid:07 smid:06 local_ts:477113991510702 global_ts:477113991321194
tid:02 smid:02 local_ts:477136243949393 global_ts:477113991321194
tid:03 smid:02 local_ts:477136243949393 global_ts:477113991321194
tid:04 smid:04 local_ts:477161370613356 global_ts:477113991321194
tid:05 smid:04 local_ts:477161370613356 global_ts:477113991321194

3.小结

  • 通过cooperative_groups的grid_group可以做所有线程块的同步,而__syncthreads()只能实现线程块内同步
  • clock64()读取的是每个SM上的时钟计数器,该计数器从设备启动时开始计数,但不同SM之间并不保证同步
  • 使用cooperative_groups的grid_group进行全网格同步(grid.sync())可以确保所有线程在同步点之前的操作都已完成
    但无法保证同步点之后的指令在所有SM上同时开始执行。由于硬件调度和指令级并行的存在,不同SM上的线程在同步点之后可能仍会有微小的执行时间差异。
    即使线程在同步后执行完全相同的指令序列,GPU的指令调度器可能会因各种原因导致不同SM上的指令开始执行的时刻略有差异,如:
    • 指令缓存命中率:不同 SM 的指令缓存状态可能不同,导致指令取指时间不同。
    • 资源竞争:SM 上的共享资源(如内存带宽)可能受到其他线程块的影响。
    • 硬件层面的不可控因素:GPU 硬件内部的微架构特性可能引入额外的延迟。
  • 查看PTX和SASS指令,该功能是通过循环读取dram中的变量并判断实现的
  • 测试的架构每个GPC有二个SM,从调度的顺序可见(4个thread_block采用的smid分别是0 2 4 6).用到了4个GPC,每个GPC出一个SM,而不是2个GPC

二.复现步骤

tee cooperative_groups.cu<<-'EOF'
#include <iostream>
#include <cuda_runtime.h>
#include <iostream>
#include <vector>
#include <stdio.h>
#include <assert.h>
#include <cstdio>
#include <cuda.h>
#include <algorithm>

#include <cooperative_groups.h>
namespace cg = cooperative_groups;

#define CHECK_CUDA(call)                      \
  do {                              \
    cudaError_t err = call;                  \
    if (err != cudaSuccess) {                 \
      std::cerr << "CUDA error at " << __FILE__ << ":" << __LINE__; \
      std::cerr << " code=" << err << " (" << cudaGetErrorString(err) << ")" << std::endl; \
      exit(EXIT_FAILURE);                  \
    }                             \
  } while (0)

__device__ unsigned long long global_clock = 0;

struct node_data
{
  unsigned long long local_ts;
  unsigned long long global_ts;
  unsigned int smid;
};

__global__ void kernel_grid_sync(node_data *pdata)
{
  unsigned int tid = threadIdx.x + blockIdx.x * blockDim.x;
  unsigned int smid;
  asm volatile("mov.u32 %0, %smid;" : "=r"(smid));  
  cg::grid_group grid = cg::this_grid();
  __prof_trigger(0);//仅用于标记代码
  grid.sync();
  __prof_trigger(1);
  pdata[tid].smid=smid;
}

__global__ void kernel(node_data *pdata)
{
  unsigned int tid = threadIdx.x + blockIdx.x * blockDim.x;
  unsigned int smid;
  asm volatile("mov.u32 %0, %smid;" : "=r"(smid));
  
  cg::grid_group grid = cg::this_grid();
  cg::thread_block block = cg::this_thread_block();
  
  __nanosleep(blockIdx.x*1000000000);
  block.sync();
  
  unsigned long long local_ts = 0;
  asm volatile ("mov.u64 %0, %clock64;" : "=l"(local_ts) :: "memory");
  if(tid==0)
  {
    global_clock=local_ts; //生成全局时钟
  }
  grid.sync();//全网格同步
  asm volatile ("mov.u64 %0, %clock64;" : "=l"(local_ts) :: "memory");
  
  pdata[tid].local_ts=local_ts;
  pdata[tid].global_ts=global_clock;
  pdata[tid].smid=smid;
}

int main(int argc,char *argv[])
{
  int deviceid=0;cudaSetDevice(deviceid); 
  int block_count=4;int block_size=2;
  int thread_size=block_count*block_size;
  node_data *pdata;
  CHECK_CUDA(cudaHostAlloc(&pdata,thread_size*sizeof(node_data),cudaHostAllocDefault));
  void *kernelArgs[] = {&pdata};
  cudaLaunchCooperativeKernel((void*)kernel_grid_sync, block_count, block_size, kernelArgs);
  cudaLaunchCooperativeKernel((void*)kernel, block_count, block_size, kernelArgs);
  CHECK_CUDA(cudaDeviceSynchronize());

  std::vector<int> indices(thread_size);
  for (int i = 0; i < thread_size; ++i) {
    indices[i] = i;
  }
  //按本地时钟大小排序(其实没有意义,因为不同SM的时钟没有可比性)
  std::sort(indices.begin(), indices.end(), [&pdata](int a, int b) {
    return pdata[a].local_ts < pdata[b].local_ts;
  });  
  for(int i=0;i<thread_size;i++)
  {
    int idx=indices[i];
    printf("tid:%02d smid:%02d local_ts:%lld global_ts:%lld\n",
        idx,pdata[idx].smid,
        pdata[idx].local_ts,
        pdata[idx].global_ts);
  }
  CHECK_CUDA(cudaFreeHost(pdata));
}
EOF
/usr/local/cuda/bin/nvcc -std=c++17 -arch=sm_86 -lineinfo -o cooperative_groups cooperative_groups.cu \
 -I /usr/local/cuda/include -L /usr/local/cuda/lib64 -lcuda
./cooperative_groups

# 用NCU查看CUDA C/PTX/SASS的对应关系
/usr/local/NVIDIA-Nsight-Compute/ncu --set full --target-processes all \
        --export ncu_report_cooperative_groups -f ./cooperative_groups

三.grid_group.sync 代码对照

1.CUDA C

  __prof_trigger(0);
  grid.sync();
  __prof_trigger(1);

2.PTX

  mov.u32 %rd6, %envreg2;   # 特殊寄存器 %envreg<32> 是PTX的32个预定义的只读寄存器集合,在内核启动之前由驱动程序初始化。
  pmevent 0;
  setp.ne.s64 %p1, %rd1, 0; # 使用关系运算符比较两个数值,然后(可选地)通过应用布尔运算符将这个结果与谓词值结合起来。
  @%p1 bra $L__BB0_2;       # 在目标处继续执行。条件分支通过使用保护谓词来指定。分支目标必须是标签。
  trap;                     # 中止执行并生成一个中断到主机CPU。
$L__BB0_2:
  mov.u32 %r2, %ctaid.x;
  mov.u32 %r3, %tid.x;
  mov.u32 %r8, %tid.y;
  add.s32 %r9, %r3, %r8;
  mov.u32 %r10, %tid.z;
  neg.s32 %r11, %r10;
  setp.ne.s32 %p2, %r9, %r11;
  barrier.sync 0;           # 在CTA内同步,0指定一个逻辑屏障资源,该资源可以是立即常量或寄存器,其值为0到15。
  @%p2 bra $L__BB0_5;
  add.s64 %rd6, %rd1, 4;
  mov.u32 %r14, %ctaid.z;
  neg.s32 %r15, %r14;
  mov.u32 %r16, %ctaid.y;
  add.s32 %r17, %r2, %r16;
  setp.eq.s32 %p3, %r17, %r15;
  mov.u32 %r18, %nctaid.z;
  mov.u32 %r19, %nctaid.x;
  mov.u32 %r20, %nctaid.y;
  mul.lo.s32 %r21, %r19, %r20;
  mul.lo.s32 %r22, %r21, %r18;
  mov.u32 %r23, -2147483647;
  sub.s32 %r24, %r23, %r22;
  selp.b32 %r13, %r24, 1, %p3;
  atom.add.release.gpu.u32 %r12,[%rd6],%r13;
$L__BB0_4:
  ld.acquire.gpu.u32 %r25,[%rd6];
  xor.b32  %r26, %r25, %r12;
  setp.gt.s32 %p4, %r26, -1;
  @%p4 bra $L__BB0_4;
$L__BB0_5:
  barrier.sync 0;
  pmevent 1;

3.SASS

 PMTRIG 0x1 
 ISETP.NE.U32.AND P0, PT, RZ, c[0x0][0x90], PT 
 ISETP.NE.AND.EX P0, PT, RZ, c[0x0][0x8c], PT, P0 
@P0  BRA 0x7f13ef054d70 
 BPT.TRAP 0x1 
 S2R R2, SR_TID.Z 
 ULDC.64 UR6, c[0x0][0x118] 
 BSSY B0, 0x7f13ef055040 
 S2R R9, SR_TID.X 
 S2R R0, SR_TID.Y 
 S2R R6, SR_CTAID.X 
 BAR.SYNC 0x0 
 IMAD.MOV R3, RZ, RZ, -R2 
 IADD3 R0, R9, R0, RZ 
 ISETP.NE.AND P0, PT, R0, R3, PT 
@P0  BRA 0x7f13ef055030 
 S2UR UR4, SR_CTAID.Z 
 S2R R3, SR_LANEID 
 IMAD.MOV.U32 R0, RZ, RZ, c[0x0][0xc] 
 S2UR UR5, SR_CTAID.Y 
 UIADD3 UR4, -UR4, URZ, URZ 
 IADD3 R2, R6, UR5, RZ 
 ISETP.NE.AND P0, PT, R2, UR4, PT 
 MEMBAR.ALL.GPU 
 VOTEU.ANY UR4, UPT, PT 
 IMAD.MOV R0, RZ, RZ, -R0 
 FLO.U32 R4, UR4 
 MOV R5, c[0x0][0x14] 
 UPOPC UR5, UR4 
 IMAD R0, R0, c[0x0][0x10], RZ 
 ERRBAR
 IMAD.MOV.U32 R2, RZ, RZ, c[0x0][0x90] 
 IMAD R0, R0, R5, -0x7fffffff 
 SEL R0, R0, 0x1, !P0 
 ISETP.EQ.U32.AND P1, PT, R4, R3, PT 
 IMAD R5, R0, UR5, RZ 
 MOV R3, c[0x0][0x8c] 
@P1  ATOM.E.ADD.STRONG.GPU PT, R5, [R2.64+0x4], R5 
 S2R R8, SR_LTMASK 
 LOP3.LUT R8, R8, UR4, RZ, 0xc0, !PT 
 POPC R8, R8 
 SHFL.IDX PT, R11, R5, R4, 0x1f 
 IMAD R0, R0, R8, R11 
 LD.E.STRONG.GPU R5, [R2.64+0x4] 
 YIELD 
 LOP3.LUT R4, R5, R0, RZ, 0x3c, !PT 
 CCTL.IVALL 
 ISETP.GT.AND P0, PT, R4, -0x1, PT 
@P0  BRA 0x7f13ef054fd0 
 BSYNC B0 
 BRA.CONV ~URZ, 0x7f13ef055080 
 MOV R2, 0x370 
 CALL.REL.NOINC 0x7f13ef0550f0 
 BRA 0x7f13ef055090 
 BAR.SYNC 0x0 
 PMTRIG 0x2 

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

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

相关文章

Java项目实战II基于Java+Spring Boot+MySQL的智能物流管理系统(文档+源码+数据库)

目录 一、前言 二、技术介绍 三、系统实现 四、文档参考 五、核心代码 六、源码获取 全栈码农以及毕业设计实战开发&#xff0c;CSDN平台Java领域新星创作者 一、前言 随着电子商务的蓬勃发展&#xff0c;物流行业迎来了前所未有的挑战与机遇。传统物流管理方式在应对海…

Acwing 快速幂

1.快速幂 作用&#xff1a;可以快速求出 a k m o d p a^k mod p akmodp的值&#xff0c;时间复杂度是 O ( l o g k ) . O( log k). O(logk). 核心思路&#xff1a;反复平方法 ①预处理出&#xff1a; a 2 0 m o d p 、 a 2 1 m o d p 、 a 2 2 m o d p 、 … 、 a 2 log ⁡ 2…

IOT-research虚拟机的中文语言设置

首先在setting&#xff08;设置&#xff09;中找到Region & Langguage 在Input Source中添加Chinese ubuntu 卡在waiting for unattended-upgr to exit的解决 sudo rm /var/cache/apt/archives/lock sudo rm /var/lib/dpkg/lock sudo rm /var/lib/dpkg/lock-frontend …

数据库管理-第245期 主流国产数据库RAC架构概览(20240929)

数据库管理245期 2024-09-29 数据库管理-第245期 主流国产数据库RAC架构概览&#xff08;20240929&#xff09;1 DMDSC2 KingBaseES RAC3 PolarDB4 Cantian5 HaloDB DLB/Data Sharding总结 数据库管理-第245期 主流国产数据库RAC架构概览&#xff08;20240929&#xff09; 作者…

HDFS不会自动退出安全模式问题

问题说明 Hadoop集群启动之后&#xff0c;HDFS进入了安全模式&#xff0c;并且不会自动退出&#xff0c;提示信息如下 Safe mode is ON. The reported blocks 1223 needs additional 3 blocks to reach the threshold 0.9990 of total blocks 1228. The minimum number of …

探索基于知识图谱和 ChatGPT 结合制造服务推荐前沿

0.概述 论文地址&#xff1a;https://arxiv.org/abs/2404.06571 本研究探讨了制造系统集成商如何构建知识图谱来识别新的制造合作伙伴&#xff0c;并通过供应链多样化来降低风险。它提出了一种使用制造服务知识图谱&#xff08;MSKG&#xff09;提高 ChatGPT 响应准确性和完整…

[Python学习日记-32] Python 中的函数的返回值与作用域

[Python学习日记-32] Python 中的函数的返回值与作用域 简介 返回值 作用域 简介 在函数的介绍中我们提到了函数的返回值&#xff0c;当时只是做了简单的介绍&#xff0c;下面我们将会进行详细的介绍和演示&#xff0c;同时也会讲一下 Python 中的作用域&#xff0c;作用域分…

fmql之Linux中断

中断 下半部机制 软中断 softirq_action tasklet 工作队列 设备树 fmql&#xff1a; 代码 目的 使能key对应GPIO的中断&#xff0c;中断服务函数为使用定时器延时15ms&#xff1b;定时器处理函数为检测key的状态 设备树修改 fmql不用把system.dtb放到SD卡。修改设备树后要在…

【RocketMQ】初识

基础概念 Message&#xff08;消息&#xff09;&#xff1a;Message 是 RocketMQ 传输的基本单元&#xff0c;包含了具体的业务数据以及一些元数据&#xff08;如消息 ID、主题、标签、发送时间等&#xff09;。消息可以是文本、二进制数据或其他任何序列化后的对象形式。Topi…

MDIO Frame介绍

在MII管理界面上传输的框架应具有表22-10所示的框架结构。位传输顺序从左到右。 IDLE (IDLE condition) MDIO上的空闲条件是高阻抗状态。所有三个状态驱动器都应被禁用,而PHY的上拉电阻器将把MDIO线拉到一个逻辑线上。 PRE (preamble) 32位前导码,都是 1 ST (start of frame…

基于Springmvc的网上书城的设计与实现

文未可获取一份本项目的java源码和数据库参考 选题意义&#xff1a; 网上书城是以当前商务的网络化、快速化实际需求为背景&#xff0c;实现图书购买的方便、快捷、送货上门等服务为前提综合信息服务系统的设计&#xff1b;实现通过Internet互联网对图书购买的相关信息进行发…

jvm专题 之 内存模型

文章目录 前言一个java对象的运行过程jvm内存分布程序的基本运行程序对象什么是对象对象的创建一、类加载检查二、对象内存分配三、初始化零值四、设置对象头五、执行初始化方法 对象的访问定位 对象与类的关系由类创建对象的顺序 对象的创建 前言 一个程序需要运行&#xff0…

编程语言图书创作要注意的事情有哪些?

编程语言图书的创作是一项复杂且具有挑战性的任务&#xff0c;需要作者深入理解技术、清晰表达&#xff0c;并考虑读者的学习体验。一本优秀的编程书籍不仅能够教授技术知识&#xff0c;更能引导读者逐步深入&#xff0c;激发他们的思考和实际应用能力。以下将详细探讨编程语言…

Python库matplotlib之三

Python库matplotlib之三 小部件(widget)小部件的基类connect_eventdisconnect_events() Buttondisconnecton_clicked应用实列 CheckButtons构造器APIs应用实列 小部件(widget) 小部件(widget)可与任何GUI后端一起工作。所有这些小部件都要求预定义一个Axes实例&#xff0c;并将…

ASP.NET Core 创建使用异步队列

示例图 在 ASP.NET Core 应用程序中&#xff0c;执行耗时任务而不阻塞线程的一种有效方法是使用异步队列。在本文中&#xff0c;我们将探讨如何使用 .NET Core 和 C# 创建队列结构以及如何使用此队列异步执行操作。 步骤 1&#xff1a;创建 EmailMessage 类 首先&#xff0c…

工作繁杂,如何防止工作遗漏遗忘?

不知道大家工作中是否有这样的情况&#xff1a; 1.工作过程中工作任务经常被打断&#xff0c;打乱正常的工作节奏&#xff1b; 2.因为不方便统一记录工作及工作要求&#xff0c;经常忘记给领导反馈工作进展&#xff1b; 3.因为工作繁多&#xff0c;经常会出现工作遗漏遗忘的…

ass字幕文件怎么导入视频mp4?ass字幕怎么编辑?视频加字幕超简单!

ass字幕文件怎么导入视频mp4&#xff1f;ass字幕怎么编辑&#xff1f;在视频制作和观看过程中&#xff0c;添加字幕是一项常见的需求&#xff0c;特别是对于外语视频或需要辅助阅读的场景。ASS&#xff08;Advanced SubStation Alpha&#xff09;字幕文件是一种常用的字幕格式&…

Redission · 可重入锁(Reentrant Lock)

前言 Redisson是一个强大的分布式Java对象和服务库&#xff0c;专为简化在分布式环境中的Java开发而设计。通过Redisson&#xff0c;开发人员可以轻松地在分布式系统中共享数据、实现分布式锁、创建分布式对象&#xff0c;并处理各种分布式场景的挑战。 Redisson的设计灵感来…

华为OD机试 - 静态扫描(Java 2024 E卷 100分)

华为OD机试 2024E卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;E卷D卷A卷B卷C卷&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;私信哪吒&#xff0c;备注华为OD&#xff0c;加…

八LAMP搭建

# LAMP ## 一、知识回顾 ### FTP samba nfs 特点 - 借用Linux用户作为映射用户&#xff0c;进行权限管理 - 软件本身还有管理控制权限 #### 客户端连接到服务器后进行读写执行等操作 &#xff0c;必须同时具有: - 软件许可的权限 vsftpd: anon upload enableYES - 文件…