一边学习一边记录(本文中英结合,专业名词统统不翻译)
在CUDA里,host和devices有不同的记忆体空间。
首先呢,CUDA的memory有很多种类啦
1. Global memory
2. Constant memory
这两种memory可以由CPU上运行的函数呼叫读写。
Global memory 这个,学过一点点CUDA的都知道,一般说device memory 指的就是它,
Constant memory 有低延迟,高带宽,但是device只能读它不能写它,并且所有线程可以同时访问同一地址。
3. Register
4. Shared memory
这两种memory是片上记忆体(on-chip),换句话说,读写速度要比前两种memory多很多,至于到底多多少,有空测试哈,而且可以以高度并行的模式读写。
Registers是被分配给单独的线程的,每个线程只能链接自己的register。
Shared memory 是被分配给block的。block里所有的线程都可以访问属于这个block的Shared Memory,共享记忆体是一个十分有效的工具,可以共享他们的输入信息和他们计算出来的中间结果。
各个记忆体的编程模型:
Global memory VS Register
1. Global memory: "The von Neumann Model": 这个记忆体在cuda编程模型中可以映射到冯诺依曼结构中的记忆体。
global memory 是在处理器芯片之外独立的记忆体,且应用的是动态随机存取存储器(Dynamic Random Access Memory,DRAM)技术。
所以会有很长的链接延迟,和相对来说较低的带宽。
2. Registers: 它有点类似于The von Neumann Model 中的“register file”,它在处理器芯片里面,所以链接的延迟非常的低,以及非常高的带宽。一般器件的Register的综合接入带宽是global memory的两个数量级大。此外,无论何时,链接Register的带宽不占用个global的带宽。另外比起链接global memory, 所需要的执行的指令也要少很多。一般的处理器对于算数指令都有内嵌的寄存器运算数,例如,浮点加法指令:
fadd r1,r2,r3
其中 r2,r3是寄存器的编号,用来提取要做加法的数,最后存到r1中去 。
如果要做加法的数字存在global memory里,首先要从global memory中把数据提取到ALU中,然后在进行浮点运算。
load r2,r4,offset
fadd r1,r2,r3
load命令可以把数据从r4中提取出来,存入r2 再进行加法。
另外还有一个是建议把运算数值存在register的原因,在现代计算机中,从一个register里调用数据一般比从global memory中调用数据所消耗的能量要低一个数量级。
补充说明:执行单位和线程之间的关系,现在我们介绍一下冯诺依曼结构,现代计算机中的线程是一个虚拟化的冯诺依曼处理器,一个线程包含了程式的一部分代码,正要执行的那部分,还有涉及到的数据和数据结构。 在基于冯诺依曼模型的计算机中,代码是存储在记忆体中的,PC不停的访问程式正要进行的那部分,IR则用来存储正要执行的指令。而寄存器和记忆体贼存储数据和数据结构。 现代处理器允许
Shared memory VS Register
他们都是 on-chip 记忆体,但是当处理期要从Shared memory中调用数据时,需要有从记忆体载入数据这个操作,如同从global memory中调用数据一样。但是因为它是片上记忆体,所以无论延迟还是带宽,都比global memory有明显的优势。但因为有load这个步骤,所以无论带宽还是延时比较register都有明显的劣势。
Shared memory存储的变量是被一个block里所有线程共享的。但是register里的变量是线程私有的。Shared memory 能很好地支持thread之间资料共享。
参考书籍:《Programming Massively Parallel Processors》
《CUDA 5.0编程指南》