CUDA内存模型

news2024/12/26 22:41:10

核函数性能并不只与线程束的执行有关。

CUDA内存模型概述

GPU和CPU内存模型的主要区别是,CUDA编程模型能将内存层次结构更好地呈现给用户,能让我们显示的控制它的行为。

对程序员来说,一般有两种类型的存储器:

  • 可编程的:需要显示的控制哪些数据存放在可编程内存中
  • 不可编程的:不能决定数据的存放位置,程序自动生成存放位置

CUDA内存模型提供了多种可编程的内存类型:

  • 寄存器
  • 共享内存
  • 本地内存
  • 常量内存
  • 纹理内存
  • 全局内存

图中所示为这些内存空间的层次结构,每个都有不同的作用域、生命周期和缓存行为。一个核函数中的线程都有自己私有的本地内存。一个线程块有自己的共享内存,对同一线程块内的所有线程可见,其内容持续线程块的整个生命周期。所有线程都可以访问全局内存。所有线程都能访问的只读空间有:常量内存和纹理内存。对一个应用程序来说,全局内存、常量内存和纹理内存中的内容具有相同的生命周期。

  1. 全局内存(Global Memory)

    • 特性:全局内存是GPU中所有线程共享的内存空间,可以被所有线程访问。
    • 优点:全局内存容量较大,适合存储大量数据。
    • 缺点:全局内存访问延迟较高,需要通过内存控制器访问,因此访问速度相对较慢。
    • 适用场景:适用于需要在不同线程之间共享数据的情况,但对访问速度要求不高的情况。
  2. 常量内存(Constant Memory)

    • 特性:常量内存是只读的内存空间,所有线程都可以读取其中的数据,但不能写入。
    • 优点:常量内存具有高速缓存,访问速度较快。
    • 缺点:常量内存容量有限(通常为64KB),且只能在程序启动时初始化。
    • 适用场景:适用于存储只读数据,且需要高速访问的情况,如常数表、查找表等。
  3. 纹理内存(Texture Memory)

    • 特性:纹理内存是一种特殊的只读内存,具有缓存和插值功能,适合于图像处理等需要纹理特性的应用。
    • 优点:纹理内存具有缓存和插值功能,可以提高某些类型数据的访问速度。
    • 缺点:容量相对较小,不能直接写入。
    • 适用场景:适用于需要纹理特性的数据访问,如图像处理、光线追踪等。

寄存器

寄存器是GPU上运行速度最快的内存空间。核函数中声明的变量通常储存在寄存器中。寄存器对每个线程来说是私有的。与核函数生命周期相同。

寄存器和线程不是一对一的,费米架构一个线程可以有63个寄存器,开普勒架构可以有255个寄存器。

如果,一个核函数使用了超过硬件限制数量的寄存器,则会用本地内存替代。这种寄存器溢出的情况会降低性能。

本地内存

核函数中符合存储在寄存器中但不能进入被该核函数分配的寄存器空间中的变量将溢出到本地内存中。

  • 在编译时,使用未知索引引用的本地数组
  • 可能会占用大量寄存器空间的较大本地结构体或数组
  • 任何不满足核函数寄存器限定条件的变量

共享内存

在核函数中使用如下修饰符修饰的变量存放在共享内存中

__shared__

每个SM都有一定数量的由线程块分配的共享内存。共享内存在核函数的范围内声明,其生命周期伴随着整个线程块。

共享内存是线程之间相互通信的基本方式。访问共享内存必须同步使用如下调用,

void __syncthreads();

SM中的一级缓存和共享内存都使用64KB的片上内存,通过静态划分,在运行时也可以进行动态配置。

片上内存(On-chip Memory)是指集成在芯片(例如GPU、CPU等处理器)内部的内存单元。与传统的外部内存(如RAM)相比,片上内存具有更低的访问延迟和更高的带宽,因为它们与处理器核心更加接近,减少了数据传输的距离和延迟。

常量内存

常量内存保存在设备内存中,每个SM都有自己专门用于缓存常量内存的缓存。

常量变量用以下修饰符修饰:

__constant__

常量变量必须在全局空间内和所有核函数之外进行声明。常量内存是静态声明的,并对同一编译单元内的所有核函数可见。

核函数只能从常量内存中读取数据,因此,常量内存必须在主机端由以下函数初始化

cudaError_t cudaMemcpyToSymbol(const void* symbol, const void* src, size_t count);

将count个字节从src指向的内存复制到symbol指向的内存中,这个变量存放在设备的全局内存或常量内存中。

线程束中的所有线程从相同的地址读取数据时,常量内存表现最好。比如,所有线程都需要读取一个公式的系数,对不同的数据根据同样的系数做相同的计算,这时,系数存放在常量内存中最好。

纹理内存

  • 特性:纹理内存是一种特殊的只读内存,具有缓存和插值功能,适合于图像处理等需要纹理特性的应用。
  • 优点:纹理内存具有缓存和插值功能,可以提高某些类型数据的访问速度。
  • 缺点:容量相对较小,不能直接写入。
  • 适用场景:适用于需要纹理特性的数据访问,如图像处理、光线追踪等。

纹理特性的数据访问指的是使用CUDA中的纹理内存(Texture Memory)来访问数据的一种特殊方式。纹理内存在访问数据时具有缓存和插值等特性,适用于某些类型的数据访问需求,例如图像处理、光线追踪等。纹理内存的特性包括以下几个方面:

  1. 缓存:纹理内存具有缓存功能,可以将最近访问的数据缓存在内存中,以提高后续访问相同数据的速度。这种缓存机制有助于减少对全局内存的访问次数,从而提高访问速度。

  2. 插值:纹理内存支持插值功能,可以对访问的数据进行插值计算,以获取平滑的插值结果。这在图像处理等需要对像素进行插值的应用中特别有用,可以减少图像处理过程中的锯齿状边缘或伪影现象。

  3. 边界处理:纹理内存支持边界处理功能,可以在访问超出边界的数据时进行特定的处理,例如将边界外的像素值设置为固定值或通过重复边界像素值来填充。

  4. 硬件优化:纹理内存的访问方式经过硬件优化,可以提高数据访问的效率,并充分利用GPU的并行计算能力。

全局内存

全局内存是GPU中最大、延迟最高且最常使用的内存。

可以使用如下修饰符静态声明一个全局内存变量

__device__

在主机端使用cudaMalloc函数分配全局内存,使用cudaFree函数释放全局内存。全局内存可以存在于应用程序的整个生命周期中,可以被所有核函数的所有线程访问。从多个线程访问全局变量时,由于线程之间不能跨线程块同步,不同线程块内的多个线程并发地修改全局内存变量可能会出现问题。

GPU缓存

与CPU缓存一样,GPU缓存是不可编程的内存。在GPU上有四种缓存

  • 一级缓存
  • 二级缓存
  • 只读常量缓存
  • 只读纹理缓存

每个SM都有一个一级缓存,所有的SM共享一个二级缓存。一级缓存和二级缓存都被用来存储本地内存和全局内存中的数据。

实践

静态声明一个全局变量,并且在一个核函数中修改值,在主机端获取修改后的值。

__device__ float num;

__global__ void test_num() {
    printf("the num is %f\n", num);
    num += 0.3;
}

int main(){
    float a = 3.14;

    cudaMemcpyToSymbol(num, &a, sizeof(float));
    test_num << <1, 1 >> > ();

    cudaMemcpyFromSymbol(&a, num, sizeof(float));
    cudaDeviceReset();

    cout << a;
    return 0;
}

这里面cudaMemcpyToSymbol函数在VS里可能会标红

显示num需要一个地址,其实并不是。在CUDA 编程指南手册里,

实际上动手做一下也会发现传地址结果会不同。

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

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

相关文章

【Qt QML】用CMake管理Qt工程

CMake是一个开源、跨平台的工具系列&#xff0c;用于构建、测试和打包软件。CMake使用简单的独立配置文件来控制软件编译过程。与许多跨平台系统不同&#xff0c;CMake被设计为与本地构建环境结合使用。 下面我们在CMake项目中使用Qt的最基本方法。首先&#xff0c;创建一个基本…

向量体系结构:向量执行时间

看《计算机体系结构 量化研究方法》做的笔记&#xff0c;接着上一篇写 计算机体系结构&#xff1a;向量体系结构介绍-CSDN博客 向量处理器工作的示例 SAXPY或DAXPY循环。 aXY SAXPY代表“单精度aX加Y”&#xff0c;进行单精度浮点数的运算&#xff0c;其中a是一个标量&#x…

测试开发工具开发 -JMeter 函数二次开发

在JMeter中开发自定义函数是一个常见的需求&#xff0c;允许我们扩展JMeter的功能以适应特定的测试需求。自定义函数可以用来处理数据&#xff0c;生成输出&#xff0c;或者执行特定的运算。通过JMeter函数二次开发可以帮我们解决实际测试过程中造数难的问题 用过JMeter的同学…

搭建vue3组件库(三): CSS架构之BEM

文章目录 1. 通过 JS 生成 BEM 规范名称1.1 初始化 hooks 目录1.2 创建 BEM 命名空间函数1.3 通过 SCSS 生成 BEM 规范样式 2. 测试 BEM 规范 BEM 是由 Yandex 团队提出的一种 CSS 命名方法论&#xff0c;即 Block&#xff08;块&#xff09;、Element&#xff08;元素&#xf…

WORD排版常见问题与解决方案

前言 近期使用word软件进行论文排版工作&#xff0c;遇到了一些常见的问题&#xff0c;记录一下&#xff0c;避免遗忘。 基本配置 系统环境&#xff1a;win10/win11 word版本&#xff1a;Microsoft Office LTSC 专业增强版 2021 问题与解决方案 问题1&#xff1a;页眉显示内…

C——双向链表

一.链表的概念及结构 链表是一种物理存储单元上非连续、非顺序的存储结构&#xff0c;数据元素的逻辑顺序是通过链表中的指针链接次序实现的。什么意思呢&#xff1f;意思就是链表在物理结构上不一定是连续的&#xff0c;但在逻辑结构上一定是连续的。链表是由一个一个的节点连…

使用递归函数,将一串数字每位数相加求和

代码结果&#xff1a; #include<stdio.h> int DigitSum(unsigned int n) {if (n > 9)return DigitSum(n / 10) (n % 10);elsereturn n; } int main() {unsigned int n;scanf("%u", &n);int sum DigitSum(n);printf("%d\n", sum);return 0; …

持续更新|UNIAPP适配APP遇到的问题以及解决方案

在使用UNIAPP开发APP的时候遇到的一些奇奇怪怪问题记录 组件样式丢失 问题&#xff1a;组件引入界面中&#xff0c;在小程序和H5环境下样式正常&#xff0c;而在APP中却出现高度异常问题 解决&#xff1a;增加view标签将组件包裹起来即可正常显示 解决前&#xff1a; 解决后…

SCI一区 | MFO-CNN-LSTM-Mutilhead-Attention多变量时间序列预测(Matlab)

SCI一区 | MFO-CNN-LSTM-Mutilhead-Attention多变量时间序列预测&#xff08;Matlab&#xff09; 目录 SCI一区 | MFO-CNN-LSTM-Mutilhead-Attention多变量时间序列预测&#xff08;Matlab&#xff09;预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.Matlab实现MFO-CNN…

JAVA第二周学习笔记

文章目录 JAVA第二周学习笔记IDEA方法格式带参数及返回值的方法方法的重载方法的内存 二维数组静态初始化动态初始化 面向对象类和对象如何定义类如何得到对象注意 封装封装的优点private关键字成员变量和局部变量 this关键字构造方法作用类型特点执行时机定义重载 标准javabea…

Linux进程——进程的创建(fork的原理)

前言&#xff1a;在上一篇文章中&#xff0c;我们已经会使用getpid/getppid函数来查看pid和ppid,本篇文章会介绍第二种查看进程的方法&#xff0c;以及如何创建子进程&#xff01; 本篇主要内容&#xff1a; 查看进程的第二种方法创建子进程系统调用函数fork 在开始前&#xff…

什么是哈希表(HashTable)?

目录 一、概念 二、哈希冲突 减少哈希冲突的办法&#xff1a; 1、设计合理的哈希函数 哈希函数设计原则&#xff1a; 常用的哈希函数&#xff1a; 2、降低负载因子&#xff08;必须重点掌握&#xff09; 哈希冲突的解决 第一类&#xff1a;闭散列 第二类&…

实时监控RTSP视频流并通过YOLOv5-seg进行智能分析处理

在完成RTSP推流之后&#xff0c;尝试通过开发板接收的视频流数据进行目标检测&#xff0c;编写了一个shell脚本实现该功能&#xff0c;关于视频推流和rknn模型的部署请看之前的内容或者参考官方的文档。 #!/bin/bash # 设置脚本使用的shell解释器为bashSEGMENT_DIR"./seg…

【模板】前缀和

原题链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 目录 1. 题目描述 2. 思路分析 3. 代码实现 1. 题目描述 2. 思路分析 前缀和模板题。 前缀和中数组下标为1~n。 前缀和&#xff1a;pre[i]pre[i-1]a[i]; 某段区间 [l,r]的和&#xff1a;pre[r]-pre[l-1] 3.…

【数学建模】2024五一数学建模C题完整论文代码更新

最新更新&#xff1a;2024五一数学建模C题 煤矿深部开采冲击地压危险预测&#xff1a;建立基于多域特征融合与时间序列分解的信号检测与区间识别模型完整论文已更新 2024五一数学建模题完整代码和成品论文获取↓↓↓↓↓ https://www.yuque.com/u42168770/qv6z0d/gyoz9ou5upv…

unity制作app(2)--主界面

1.先跳转过来&#xff0c;做一个空壳&#xff01;新增场景main为4号场景&#xff01; 2.登录成功跳转到四号场景&#xff01; 2.在main场景中新建canvas&#xff0c;不同的状态计划用不同的panel来设计&#xff01; 增加canvas和底图image 3.突然输不出来中文了&#xff0c;浪…

【19-文本数据处理:Scikit-learn中的自然语言处理技术】

文章目录 前言理解文本数据文本预处理文本清洗分词停用词去除向量化文本数据词袋模型TF-IDF变换构建文本分类模型模型评估与调优结论前言 欢迎回到我们的Scikit-learn系列,在这篇文章中,我们将探讨如何使用Scikit-learn来处理文本数据,这是自然语言处理(NLP)的基础。你将学…

为家庭公网IP配置DDNS域名

文章目录 域名配置域名更新frp配置修改 在成功完成frp改造Windows笔记本实现家庭版免费内网穿透之后&#xff0c;某天我突然发现内网穿透失效了&#xff0c;一番排查之后原来是路由器对应的公网IP更换了。果然我分到的并不是固定的公网IP&#xff0c;而是会定期变化的。为了免受…

中间件之异步通讯组件RabbitMQ入门

一、概述 微服务一旦拆分&#xff0c;必然涉及到服务之间的相互调用&#xff0c;目前我们服务之间调用采用的都是基于OpenFeign的调用。这种调用中&#xff0c;调用者发起请求后需要等待服务提供者执行业务返回结果后&#xff0c;才能继续执行后面的业务。也就是说调用者在调用…

解决IDEA下springboot项目打包没有主清单属性

1.问题出现在SpringBoot学习中 , 运行maven打包后无法运行 报错为spring_boot01_Demo-0.0.1-SNAPSHOT.jar中没有主清单属性 SpringBoot版本为 2.6.13 Java 版本用的8 解决方法 1.执行clean 删除之前的打包 2.进行打包规范设置 2.1 3.进行问题解决 (借鉴了阿里开发社区) 使用…