简介

本合集主要介绍我在开发分布式异构训练框架时的CUDA编程实践和性能优化的相关内容。主要包含以下几个部分:

  1. 介绍CUDA的基本概念和架构,帮助读者建立对CUDA的初步认识,包括硬件架构/CUDA基础等内容
  2. 介绍一些性能优化技巧和工具,帮助读者优化CUDA程序的执行效率
  3. 结合具体的代码示例来说明一个cuda程序的优化思路和结果, 帮助读者更好地理解和掌握CUDA编程和性能优化的实践方法

希望通过本文档,能够帮助大家写出更高效的CUDA程序。下面我们就开始吧~

1. 硬件架构

要说清楚为什么GPU比CPU更适合大规模并行计算, 要从硬件层面开始说起

以当前较主流的硬件i9-14900k和A100为例:

i9-14900k: 24核心, 32线程(只能在16个能效核上进行超线程), L2: 32MB, L3: 36MB, 内存通信带宽 89.6GB/s

A100: 108 SM, 6912 CUDA core, 192KB L1, 60MB L2, 40GB DRAM.

我个人的理解, GPU的运算核心之所以远多于CPU, 是因为远少于CPU的控制逻辑. GPU每个core内不需要考虑线程调度的情况, 不需要保证严格一致的运算顺序, 另外每个sm都有自己独立的寄存器和L1, 对线程的切换重入非常友好, 所以更适合大规模数据的并行运算. 而这种设计方式也会对程序员提出更高的要求, 纯CPU程序可能写的最好的代码和最差的情况有个2/3倍的性能差距就很大了, 而CUDA kernel可能会相差几十倍甚至几百倍.

HBM(High-Bandwidth Memory) :HBM是高带宽内存,也就是常说的显存, 这张图里的DRAM。 带宽: 1.5TB/s

L2 Cache:L2 Cache是GPU中更大容量的高速缓存层,可以被多个SM访问。L2 Cache还可以用于协调SM之间的数据共享和通信。 带宽: 4TB/s

SM(Streaming Multiprocessor) :GPU的主要计算单元,负责执行并行计算任务。每个SM都包含多个CUDA core,也就是CUDA里Block执行的地方, 关于block_size如何设置可以参考block_size设置, 跟随硬件不同而改变, 通常为128/256

L1 Cache/SMEM:, 也叫shared_memory, 每个SM独享一个L1 Cache,CUDA里常用于单个Block内部的临时计算结果的存储, 比如cub里的Block系列方法就经常使用, 带宽: 19TB/s

SMP(SM partition): A100中有4个. 每个有自己的wrap调度器, 寄存器等.

CUDA Core: 图里绿色的FP32/FP64/INT32等就是, 是thread执行的基本单位

Tensor Core: Volta架构之后新增的单元, 主要用于矩阵运算的加速

WARP(Wavefront Parallelism) :WARP指的是一组同时执行的Thread,固定32个, 不够32时也会按32分配. wrap一个线程对内存操作后, 其他wrap内的线程是可见的.

Dispatch Unit: 从指令队列中获取和解码指令,协调指令的执行和调度

Register File: 寄存器用于存储临时数据、计算中间结果和变量。GPU的寄存器比CPU要多很多

2. cuda基础

cuda基础语法上和c/c++是一致的. 引入了host/device定义, host指的是cpu端, device指的是gpu端

个人感觉最难的部分在于并行的编程思想和cpu编程的思想差异比较大. 我们以一个向量相加的demo程序举例:

__global__ void add_kernel(int *a, int *b, int *c, int n) {
int index = threadIdx.x + blockIdx.x * blockDim.x;
if (index < n) {
c[index] = a[index] + b[index];
}
} int main() {
int *a, *b, *c;
int *d_a, *d_b, *d_c;
int n = 10000;
int size = n * sizeof(int);
cudaMalloc((void**)&d_a, size);
cudaMalloc((void**)&d_b, size);
cudaMalloc((void**)&d_c, size);
a = (int*)malloc(size);
random_ints(a, n);
b = (int*)malloc(size);
random_ints(b, n);
c = (int*)malloc(size);
cudaMemcpy(d_a, a, size, cudaMemcpyHostToDevice);
cudaMemcpy(d_b, b, size, cudaMemcpyHostToDevice);
//cuda kernel
add_kernel<<<(n + threads_per_block - 1)/threads_per_block, threads_per_block>>>(d_a, d_b, d_c, n);
cudaMemcpy(c, d_c, size, cudaMemcpyDeviceToHost); cudaFree(d_a);
cudaFree(d_b);
cudaFree(d_c); return 0;
}

描述符

cuda新增了三个描述符:

__global__: 在device上运行, 可以从host/device上调用, 返回值必须是void, 异步执行.

__device__: 在device上运行和调用

__host__: 只能在host上执行和调用

CUDA Kernel

cuda_kernel是由<<<>>>围起来的, 里面主要有4个参数用来配置这个kernel <<<grid_size, block_size, shared_mem_size, stream>>>

grid_size: 以一维block为例, grid_size计算以 (thread_num + block_size - 1) / block_size 计算大小

block_size: 见上面SM部分介绍

shared_mem_size: 如果按 __shared__ int a[] 方法声明共享内存, 需要在这里填需要分配的共享内存大小. 注意不能超过硬件限制, 比如A100 192KB

stream: 异步多流执行时的cuda操作队列, 在这个流上的所有kernel是串行执行的, 多个流之间是异步执行的. 后续会在异步章节里详细介绍

整个过程如下图, 先通过cudaMemcpy 把输入数据copy到显存->cpu提交kernel->gpu kernel_launch->结果写回线程->DeviceToHost copy回内存.

add_kernel 相当于我们将for循环拆分为了每个线程只处理一个元素的相加的并行执行. 通过nvcc编译后就完成了第一个kernel的编写. 下一篇会以一个具体的例子来讲如何进行kernel的性能分析和调优.

常用库

thrust: cuda中类似于c++ STL的定位, 一些类似于STL的常见算法可以在这里找到现成的实现, 比如sort/reduce/unique/random 等. 文档: https://nvidia.github.io/cccl/thrust/api/namespace_thrust.html

cudnn: 神经网络加速的常用库. 包含卷积/pooling/softmax/normalization 等常见op的优化实现.

cuBlas: 线性代数相关的库. 进行矩阵运算时可以考虑使用, 比如非常经典的矩阵乘法实现cublasSgemm

Cub: wrap/block/device级的编程组件, 非常常用. 文档: https://nvidia.github.io/cccl/cub/

nccl: 集合通信库. 用于卡间通信/多机通信

相关资料

cuda编程指导手册: https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#programming-model

性能分析工具Nsight-System & Nsight-Compute: https://docs.nvidia.com/nsight-systems/index.html

CUDA程序优化-1.基础介绍的更多相关文章

  1. 可分离滤波器设计高斯滤波 CUDA程序优化, 实验记录

    环境:RTX2060 ,1920X1080p ,循环10次, kernal_size=8 一 .测试前128个线程拷贝到dst数据的性能  ,只测试行卷积, block=(128+2r)X1 1. 使 ...

  2. CUDA基础介绍

    一.GPU简介 1985年8月20日ATi公司成立,同年10月ATi使用ASIC技术开发出了第一款图形芯片和图形卡,1992年4月ATi发布了Mach32图形卡集成了图形加速功能,1998年4月ATi ...

  3. php数据结构课程---1、数据结构基础介绍(程序是什么)

    php数据结构课程---1.数据结构基础介绍(程序是什么) 一.总结 一句话总结: 程序=数据结构+算法 设计好数据结构,程序就等于成功了一半. 数据结构是程序设计的基石. 1.数据的逻辑结构和物理结 ...

  4. 【ABAP系列】SAP ABAP基础-程序优化及响应速度之LOOP

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[ABAP系列]SAP ABAP基础-程序优化及 ...

  5. Java 程序优化 (读书笔记)

    --From : JAVA程序性能优化 (葛一鸣,清华大学出版社,2012/10第一版) 1. java性能调优概述 1.1 性能概述 程序性能: 执行速度,内存分配,启动时间, 负载承受能力. 性能 ...

  6. Linux基础介绍【第一篇】

    Linux简介 什么是操作系统? 操作系统,英文名称Operating System,简称OS,是计算机系统中必不可少的基础系统软件,它是应用程序运行以及用户操作必备的基础环境支撑,是计算机系统的核心 ...

  7. 关于C#程序优化的五十种方法

    关于C#程序优化的五十种方法    这篇文章主要介绍了C#程序优化的五十个需要注意的地方,使用c#开发的朋友可以看下   一.用属性代替可访问的字段 1..NET数据绑定只支持数据绑定,使用属性可以获 ...

  8. GPU 编程入门到精通(四)之 GPU 程序优化

    博主因为工作其中的须要,開始学习 GPU 上面的编程,主要涉及到的是基于 GPU 的深度学习方面的知识,鉴于之前没有接触过 GPU 编程.因此在这里特地学习一下 GPU 上面的编程.有志同道合的小伙伴 ...

  9. 一步步做程序优化-讲一个用于OpenACC优化的程序(转载)

    一步步做程序优化[1]讲一个用于OpenACC优化的程序 分析下A,B,C为三个矩阵,A为m*n维,B为n*k维,C为m*k维,用A和B来计算C,计算方法是:C = alpha*A*B + beta* ...

  10. professional cuda c programming--CUDA库简单介绍

    CUDA Libraries简单介绍   上图是CUDA 库的位置.本文简要介绍cuSPARSE.cuBLAS.cuFFT和cuRAND.之后会介绍OpenACC. cuSPARSE线性代数库,主要针 ...

随机推荐

  1. 【详谈 Delta Lake 】系列技术专题 之 湖仓一体( Lakehouse )

    简介: 本文翻译自大数据技术公司 Databricks 针对数据湖 Delta Lake 的系列技术文章.众所周知,Databricks 主导着开源大数据社区 Apache Spark.Delta L ...

  2. [FAQ] 夏玉米 按规则查询域名靠谱吗 ?

    很早就有一个网站叫 夏玉米,可以按规则查询和注册域名,那么它真如我们想的那样 可以找到好域名吗? 虽然看起来很好用,实际上夏玉米的查询只是针对它自己的数据库,不包含未在其平台注册的域名,所以大家要失望 ...

  3. dotnet OpenXML 读取 PPT 形状边框定义在 Style 的颜色画刷

    本文来和大家聊聊在 PPT 形状使用了 Style 样式的颜色画刷读取方法 在开始之前,期望大家已了解如何在 dotnet 应用里面读取 PPT 文件,如果还不了解读取方法,请参阅 C# dotnet ...

  4. dotnet 教你写一个可以搞炸本机所有 WCF 应用的程序方法

    作为团队里面挖掘机出身的我,怎么能不多挖一些坑好将小伙伴们都埋进去呢.本文来告诉大家一个有趣且简单的方法,此方法可以将本机的 WCF 玩坏,不敢说真的搞炸本机所有 WCF 应用,但搞炸大部分基于 WC ...

  5. 第8讲 browse命令的使用技巧

    第8讲 browse命令的使用技巧 1.浏览所有parts,使用技巧 选中工程文件*.dsn/Edit/Browse/Parts.列出工程中用到的所有元件,方便在画完原理图后,查看哪些元件没有编号或数 ...

  6. SAP集成技术(八)成熟度模型

    成熟度模型的目的在于使用模型和标准来评估当前的集成能力,并确定必须建立哪些能力,以达到期望的成熟度级别. 成熟度级别描述了一个特定主题复杂性对于某种方法或模型的成熟度.基于定义的需求和标准的分类,得出 ...

  7. 开源文档预览项目 kkFileView (9.9k star) ,快速入门

    kkFileView 是一款文件文档在线预览解决方案,采用流行的 Spring Boot 框架构建,易于上手和部署. 该项目基本支持主流办公文档的在线预览,包括但不限于 doc.docx.xls.xl ...

  8. tomcat(2)- tomcat目录结果和配置文件

    目录 1 Tomcat目录结构 2 Tomcat的配置文件 2.1 server.xml配置文件 2.2 server.xml配置文件结构 2.3 WEB应用自动部署 2.4 配置文件各个组件的关联 ...

  9. blocks (单调栈)

    题目描述 解析 对于这道题,他要求大于k的数进行操作,所以直接让每个数减k,然后用前缀和维护一下与0比较就可以了,因为一段区间和的平 均值大于k的话,那么这就是一个合法区间,即为操作后的这个区间和大于 ...

  10. [kernel] 带着问题看源码 —— 进程 ID 是如何分配的

    前言 在<[apue] 进程控制那些事儿>一文中,曾提到进程 ID 并不是唯一的,在整个系统运行期间一个进程 ID 可能会出现好多次. > ./pid fork and exec c ...