CUDA提高Memory throughput的方法

news/2025/3/14 19:51:28/文章来源:https://www.cnblogs.com/smartljy/p/18772765

CUDA提高Memory throughput的方法

内容

在 CUDA 编程中,提高内存吞吐量(Memory Throughput)是优化性能的关键。以下是系统化的优化策略和示例:


1. 理解内存层次与带宽

CUDA 设备的内存层次包括:

  • 全局内存(Global Memory):高延迟,低带宽(但总量最大)。
  • 共享内存(Shared Memory):低延迟,高带宽(但容量小)。
  • 寄存器(Registers):最快,但线程私有。
  • 常量内存(Constant Memory):适合只读数据,有缓存。
  • 纹理内存(Texture Memory):适合空间局部性强的访问。

优化核心思想:减少全局内存访问,利用高速内存的局部性


2. 全局内存优化

(1) 合并访问(Coalesced Access)

全局内存的访问以 32/128 字节对齐的事务(Transaction) 为单位。若线程束(Warp)的 32 个线程访问连续内存,可合并为少数事务。

  • 优化前(分散访问)

    // 每个线程访问间隔 k 的地址(非连续)
    __global__ void kernel(float *out, float *in, int k) {int tid = blockIdx.x * blockDim.x + threadIdx.x;out[tid] = in[tid * k];  // 低效,访问不连续
    }
    
  • 优化后(连续访问)

    // 所有线程访问连续地址
    __global__ void kernel(float *out, float *in) {int tid = blockIdx.x * blockDim.x + threadIdx.x;out[tid] = in[tid];  // 高效,合并访问
    }
    

(2) 向量化加载(Vectorized Load)

使用 float2/float4int2/int4 类型,减少指令数和事务数:

// 每个线程一次加载 4 个 float
__global__ void kernel(float4 *out, float4 *in) {int tid = blockIdx.x * blockDim.x + threadIdx.x;float4 val = in[tid];out[tid] = val;
}

(3) 内存对齐

确保数据地址对齐到 128 字节(全局内存事务大小):

cudaMalloc((void**)&data, size * sizeof(float) + 128);
data = (float*)(((size_t)data + 127) & ~127);  // 手动对齐

3. 共享内存优化

(1) Bank 冲突避免

共享内存被划分为 32 个 Bank(默认 4 字节宽)。若多个线程访问同一 Bank 的不同地址,会触发冲突(Bank Conflict)。

  • 优化前(Bank 冲突)

    __shared__ float s_data[32][32];
    // 线程 (x, y) 访问 s_data[y][x],同一列(同一 Bank)
    float val = s_data[threadIdx.y][threadIdx.x];
    
  • 优化后(无冲突)

    __shared__ float s_data[32][33];  // 添加 Padding
    // 线程 (x, y) 访问 s_data[y][x],分散到不同 Bank
    float val = s_data[threadIdx.y][threadIdx.x];
    

(2) 共享内存分块(Tiling)

将全局内存数据分块加载到共享内存,减少重复访问:

__global__ void matrixMul(float *C, float *A, float *B, int N) {__shared__ float s_A[16][16], s_B[16][16];int bx = blockIdx.x, by = blockIdx.y;int tx = threadIdx.x, ty = threadIdx.y;// 分块加载到共享内存s_A[ty][tx] = A[(by * 16 + ty) * N + bx * 16 + tx];s_B[ty][tx] = B[(bx * 16 + ty) * N + by * 16 + tx];__syncthreads();// 使用 s_A 和 s_B 进行计算// ...
}

4. 其他优化技术

(1) 常量内存与只读缓存

对只读数据使用 const__restrict__ 关键字,并利用常量内存:

__constant__ float const_data[1024];
// 或使用只读缓存(CUDA 8+)
__global__ void kernel(const float *__restrict__ data) {// 编译器自动优化为利用 L1 缓存
}

(2) 统一内存(Unified Memory)

简化内存管理,但需注意性能:

cudaMallocManaged(&data, size);
// 在 GPU 和 CPU 之间自动迁移数据(适合非频繁访问场景)

(3) 异步内存传输

重叠计算与数据传输:

cudaStream_t stream;
cudaStreamCreate(&stream);
cudaMemcpyAsync(dst, src, size, cudaMemcpyHostToDevice, stream);
kernel<<<grid, block, 0, stream>>>(...);
cudaStreamSynchronize(stream);

5. 性能分析工具

使用工具验证优化效果:

  • Nsight Compute:分析内核的内存访问模式。
  • nvprof:查看全局内存吞吐量和事务数:
    nvprof --metrics gld_throughput,gst_throughput ./app
    

总结

[
\boxed{
\begin{aligned}
&\text{提高 CUDA 内存吞吐量的关键:} \
&\text{1. 全局内存合并访问与对齐} \
&\text{2. 共享内存避免 Bank 冲突} \
&\text{3. 利用向量化加载与高速缓存} \
&\text{4. 使用分析工具验证优化效果}
\end{aligned}
}
]
]

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

探秘Transformer系列之(13)--- FFN

从零开始解析Transformer,目标是:(1) 解析Transformer如何运作,以及为何如此运作,让新同学可以入门;(2) 力争融入一些比较新的或者有特色的论文或者理念,让老鸟也可以有所收获。探秘Transformer系列之(13)--- FFN 目录探秘Transformer系列之(13)--- FFN0x00 概述0x01…

EXCEL-时间函数

💖简介 在Excel中,时间函数用于处理和操作日期和时间数据; 以下是Excel中常用的时间函数及其常见应用场景的总结.📖函数 ⭐时间函数基础 🌟TIME语法:TIME(hour, minute, second) 功能:将小时、分钟、秒转换为时间序列号(0到0.99999999之间的数值)。 示例:TIME(9,30…

day29linux三剑客----sed

day29linux三剑客----sed单个正则字符还认识组合到一起就晕了,怎么办?本质还是对单个字符没理解.认识*认识.*组合到就一起就蒙了,为什么?还是没想明白.的意义,*的意义正则表达式,从左向右,逐步理解单个字符的意义怎么做? 1.思维脑图写没写? 2.每一个正则表达式的符号,…

3.14 学习记录

基于Android Studio 完成了简单的石家庄地铁购票APP

Android配置

将grade-wrapper.properties中地址改为 https://mirrors.cloud.tencent.com/gradle/gradle-8.11.1-bin.zip 等待下载。一般要几个小时。

sqlserver 的视图创建

首先,什么是视图?视图是一种数据库对象,是从一个或者多个数据表或视图中导出的虚表,视图的结构和数据是对数据表进行查询的结果,只存放视图的定义,不存放视图对应的数据; 其结构和和数据是建立在对表的查询基础上,故表中的数据发生变化,从视图中查询出的数据也随之改变…

day:21 python——判断语句

一.if语句 (1)单分支: 格式: if 判断条件: 执行语句块 else: 执行语句块2 备注:判断条件 if中可以使用比较运算符,<,!=,==,>=,<=在学习自动化中也可以用if语句断言, 案例1: a=10 if a != 10: print("你中奖了") else: print("谢谢惠顾"…

clickhouse 开启认证

配置文件说明 默认路径:/etc/clickhouse-server/users.xml 密码存储类型 明文密码(不推荐) <password>qwerty</password> <!-- 直接明文存储 --> SHA256 哈希 <password_sha256_hex>5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d15…

二分查找--java进阶day06

1.二分查找 https://kdocs.cn/l/ciMkwngvaWfz?linkname=150996908 二分查找:每一次查找都从中间的元素查起,根据比较的大小来折半,以此类推,直到最后找到该数2.二分查找的前提 确保查找的数组是排好序的数组,否则就会出错 如下图,假设我们要找的是200,箭头指向88,发现…

Fastjson 和Jackson 兼容性问题

起因是因为java类里面多层嵌套验证发现APIFOX调用接口验证无法生效 发现是因为没有赋值嵌套类 经过查看属性填充的源码,requestbody传参,用的是Fastjson的注解但是走到了AbstractJackson2HttpMessageConverter类的readJavaType方法 一查发现可能有不兼容的问题,Jackson 需要…

modelsim保存波形图为图片报错:image file format bmp is unknown

在波形窗口依次点击 File-->Export-->Image 如果版本低于2020.2,会报错:解决方案为: 在命令框输入:package require Img 解决方案来自Why cant I export the wave image in bmp format in the ModelSim-Intel FPGA Edition and Questa-Intel FPGA Edition simulator?…

第十二课(2024年)基准测试与评估

来看一下讲师认为的理想的开发过程Deploy的Absolute的意思:部署阶段的评测指标是绝对的,之前的阶段都是从若干个模型中选择最好的,但最后一个阶段就只剩下一个模型了,我们必须要让这个模型的准确率达到一个设定的绝对阈值 Publish的Standardized和Reproducible:标准化和可…