GPU内存分级

在NVIDIA的GPU中,内存(GPU的内存)被分为了全局内存(Global memory)、本地内存(Local memory)、共享内存(Shared memory)、寄存器内存(Register memory)、常量内存(Constant memory)、纹理内存(Texture memory)六大类。这六类内存都是分布在在RAM存储芯片或者GPU芯片上,他们物理上所在的位置,决定了他们的速度、大小以及访问规则。

如下图,整张显卡PCB电路板上的芯片主要可以分为三类:

1. GPU芯片,也是整张显卡的核心,负责执行计算任务。

2. DDR3存储芯片,其在显卡中相对与GPU的地位相当于电脑中内存条对于CPU,只是放在了显卡上专供GPU使用。

3. 时钟、电源等其他辅助功能的芯片。

显卡的内存可以分为GPU片内(On-Chip)存储体和位于DDR3存储芯片中的存储体。片内存储体的访问延迟(Latency)远低于片外存储体的访问延迟(Latency),当然片内存储体也有更快的传输速度。

全局内存(Global memory),位于片外存储体中。容量大、访问延迟高、传输速度较慢。在2.X计算力之后的GPU上,都会使用二级缓存(L2 cache)做缓冲,达到较快的传输速度,但这并不能减少访问的延迟(Latency)。

  • 所有数据都必须先传入到这里,或者从这里传出。
  • 用户通过调用CUDA函数控制全局内存的分配空间、传入数据、传出数据。例如:

下面详细介绍下GM107中SMM的内部结构:

指令缓存(Instruction Cache)存放核函数中的的指令。

指令缓冲区(Instruction Buffer)Core访问它的速度比指令缓存更快,但是空间更小。

线程束调度器(Warp Scheduler)调度各个线程束执行、挂起等。

流处理器(Core 或 Stream Processor)

一级缓存(L1 Cache)、纹理内存(Texture),他们公用同一片cache区域,可以通过调用CUDA函数设置各自的所占比例。

共享内存(Shared Memory)

寄存器区(Register File)供各条线程在执行时存放临时变量的区域。

本地内存(Local memory),一般位于片内存储体中,在核函数编写不恰当的情况下会部分位于片外存储器中。当一个线程执行核函数时,核函数的变量、数组、结构体等都存放在本地内存(Local memory)中。此时存在两种情况:

  • 当我们核函数中的变量较少,寄存器区(Register File)的大小足够放下这些变量,那么他们就放在GPU芯片的流处理器组(SM)中的寄存器区。
  • 当核函数中有大数组、大结构体以至于寄存器区放不下他们,编译器在编译阶段就会将他们放到片外的DDR3芯片中(最好的情况也会被扔到L2 Cache中),且将他们标记为“Local”型。核函数在执行时会反复读取他们,这也就大大降低了核函数运行效率,这是我们一定要避免的情况!

《CUDA Programming Guide》

中重点提到:

共享内存(Shared memory)位于每个流处理器组中(SM)中,其访问速度仅次于寄存器,特点是一个线程块(Block)中的所有线程都可以访问。主要存放频繁修改的变量。

寄存器内存(Register memory)位于每个流处理器组中(SM)中,访问速度最快的存储体,用于存放线程执行时所需要的变量。

常量内存(Constant memory)位于每个流处理器(SM)中和片外的RAM存储器中。常量内存是只读的,不能在核函数执行的过程中被修改。但是可以在核函数执行前,通过重新传入数据进行修改。

  • 当常量内存被初始化的时候,它会先全部保存在片外的RAM中,然后使用8KB(具体数值随显卡型号变化)的一级缓存 作为缓冲,可以将访问延迟(Latency)缩到很短。
  • 当一个线程束中的各个线程访问的不是一段连续的内存时,如果访问的是全局内存,则可能会访问多次,造成时间的浪费;但如果访问的是常量内存,只要访问的数据是在一级缓存内,则立刻取得数据。

纹理内存(Texture memory)位于每个流处理器(SM)中和片外的RAM存储器中。它与常量内存非常类似。但是他有两点不同:

  • 纹理内存,顾名思义就是专门用于纹理贴图操作的,故在该操作上使用纹理内存更加高效。
  • 纹理内存具有广播机制。

第一句话比较难度,大致意思是在进行纹理贴图操作或几何表面访问的操作时,由于访问数据的方式不符合访问全局内存和常量内存的访问规律,导致访问速度下降,但是纹理内存可以解决这一问题。

推荐阅读:

GPU的工作原理

两段小视频轻松理解CPU & GPU的工作原理

本文分享自微信公众号 - 人人都是极客(rrgeek)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-04-23

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Linux 内存相关问题汇总

    这篇文章是对 Linux 内存相关问题的集合,工作中会有很大的帮助。关注公号的朋友应该知道之前我写过从内核态到用户态 Linux 内存管理相关的基础文章,在阅读...

    刘盼
  • Linux 内存相关问题汇总

    这篇文章是对 Linux 内存相关问题的集合,工作中会有很大的帮助。关注公号的朋友应该知道之前我写过从内核态到用户态 Linux 内存管理相关的基础文章,在阅读...

    刘盼
  • Linux页框分配器之内存碎片化整理

    指分配给用户的内存空间中未被使用的部分。例如进程需要使用3K bytes物理内存,于是向系统申请了大小等于3Kbytes的内存,但是由于Linux内核伙伴系统算...

    刘盼
  • MMU那些事儿

    [导读] 本文从内存管理的发展历程角度层层递进,介绍MMU的诞生背景,工作机制。而忽略了具体处理器的具体实现细节,将MMU的工作原理从概念上比较清晰的梳理了一遍...

    逸珺
  • JVM学习系列学习三

        在Java中,创建的所有引用对象类型,都在堆内存中。堆内存中的数据由GC对其进行管理的。其实堆内存也是GC主要管理的地方。

    凯哥Java
  • Zephyr 内存分配

    int k_mem_pool_alloc(struct k_mem_pool *p, struct k_mem_block *block, size_t si...

    无限之生
  • 【春节红包系列】一次"内存泄漏"引发的血案

    2017年末,手Q春节红包项目期间,为保障活动期间服务正常稳定,我对性能不佳的Ark Server进行了改造和重写。重编发布一段时间后,结果发现新发布的Svr的...

    后台搬砖鹅
  • 一图解千愁,jvm内存从来没有这么简单过!

    看到这张图的同学,千万不要到处分享。我们仅限于小范围讨论,因为这张图威力很大,是我花了10年时间才画出来的!

    xjjdog
  • 调整JVM内存大小

    JAVA程序启动时JVM都会分配一个初始内存和最大内存给这个应用程序。这个初始内存和最大内存在一定程度都会影响程序的性能;Tomcat默认可以使用的内存为128...

    MonroeCode
  • 内存池介绍与经典内存池的实现

    利用默认的内存管理函数new/delete或malloc/free在堆上分配和释放内存会有一些额外的开销。

    Dabelv

扫码关注云+社区

领取腾讯云代金券