当前位置: 首页 > news >正文

【CUDA】《CUDA编程:基础与实践》CUDA加速的关键因素

CUDA事件计时

CUDA提供了一种基于CUDA事件(CUDA event)的计时方式,可用来给一段CUDA代码(可能包含主机代码和设备代码)计时。
对计时器的封装:

class CUDATimeCost {
public:void start() {elapsed_time_ = 0.0;// 初始化cudaEventcheckCudaRuntime(cudaEventCreate(&start_));checkCudaRuntime(cudaEventCreate(&stop_));// 记录开始事件checkCudaRuntime(cudaEventRecord(start_));cudaEventQuery(start_);}void stop() {// 记录结束事件checkCudaRuntime(cudaEventRecord(stop_));checkCudaRuntime(cudaEventSynchronize(stop_));// 计算事件差checkCudaRuntime(cudaEventElapsedTime(&elapsed_time_, start_, stop_));checkCudaRuntime(cudaEventDestroy(start_));checkCudaRuntime(cudaEventDestroy(stop_));}/*** @brief Get the elapsed time ms* * @return float */float get_elapsed_time() {return elapsed_time_;}private:cudaEvent_t start_, stop_;float elapsed_time_{0.0};
};

比较单精度和双精度的性能差异

测试的GPU为 MX450 显存带宽为:10GBps

double : 58.4116 ms
float  : 27.7594 ms

有效显存带宽

8×107×4B2.7×10−2(1)\frac{8 \times 10^7 \times 4 B}{2.7 \times 10^{-2}}\tag{1} 2.7×1028×107×4B(1)

几个影响GPU加速的关键因素

1. 数据传输比

当我们将计时器只计算运算的时间时发现,在向量求和的程序中,大部分的时间都消耗在了数据拷贝上。

  • GPU的显存带宽理论值(几百吉比特)远大于PCIex16 (16GB/s)的带宽。相差几十倍
  • 在CUDA编程的过程中应该尽可能减少数据在主机和设备之间的拷贝

2. 算术强度

一个问题的算术强度指的是其中算术操作的工作量与必要的内存操作的工作量之比。例如在求和操作中,去两次数据、存一次数据,但是只做一次计算,这样的算术强度就不高。在CUDA中,设备内存的读、写都是比较耗时的。

3. 并行规模

并行规模可用GPU中的总的线程数目来衡量。从硬件的角度来看,一个GPU由多个流处理器(streaming multiprocessor, SM)构成,而每个SM中有若干CUDA核心。每个SM是相对独立的。一个SM中最多能驻留线程的个数为1024(图灵架构),开普勒架构到伏特架构最多驻留的线程个数为2048. 一块GPU中一般有几个到几十个SM。所以一块GPU一共可以驻留几万到几十万个线程。所以一个核函数定义的线程数目小于这个数的话,就很难得到很高的加速比。所以对于数据规模很小的问题,用GPU很难得到可观的加速。

总结

一个CUDA程序能够获得高性能的必要条件有如下几点:

  • 数据传输比例较小
  • 核函数的算术强度较高。
  • 核函数中定义的线程数目较多

在编写优化CUDA程序时,一定要想方设法做到如下几点:

  • 减少主机与设备之间的数据传输
  • 提高核函数的算术强度
  • 增大核函数的并行规模
http://www.lryc.cn/news/39306.html

相关文章:

  • 数据结构【Golang实现】(四)——双向循环链表
  • 【Redis】高可用架构之哨兵模式 - Sentinel
  • 图片的美白与美化
  • 面试官:关于CPU你了解多少?
  • UI自动化测试-Selenium的使用
  • 嵌入式学习笔记——STM32的USART相关寄存器介绍及其配置
  • Android setContentView流程分析(一)
  • doris数据库操作数字遇到的问题
  • 3.13文件的IO操作
  • ffmpeg使用
  • spark中的并行度(分区数)/分区器如何确定
  • 00后女生“云摆摊”两周赚1.5万,实体店转战线上真的能赚钱吗?
  • 华为OD机试题 - 最优资源分配(JavaScript)| 机考必刷
  • 利用python判断字符串是否为回文
  • GDB 调用之ptype、set variable
  • 并发编程---阻塞队列(五)
  • 本科课程【计算机组成原理】实验1 - 输出ABCD程序的生成
  • Java并发编程(2) —— 线程创建的方式与原理
  • 你写的js性能有多差你知道吗 | js性能优化
  • 线程的状态、状态之间的相互转换
  • Java8使用Lambda表达式(流式)快速实现List转map 、分组、过滤等操作
  • C++之深浅拷贝
  • CoreLocation的一切
  • HashMap原理
  • STM32入门笔记(02):独立看门狗(IWDG)和窗户看门狗(WWDG)(SPL库函数版)
  • javaSE系列之方法与数组的使用
  • 常用命令总结
  • 【Linux:程序地址空间--原来操作系统也喜欢画大饼】
  • Python实现简单信号滤波实战
  • Java(110):非对称加密RSA的使用(KeyPair生成密钥)