计算机视觉 基于CUDA编程的入门与实践 线程及同步二

一、存储器架构

        在GPU上的代码执行被划分为流多处理器、块和线程。GPU有几个不同的存储器空间,每个存储器空间都有特定的特征和用途以及不同的速度和范围。这个存储空间按层次结构划分为不同的组块,比如全局内存、共享内存、本地内存、常量内存和纹理内存,每个组块都可以从程序中的不同点访问。

计算机视觉 基于CUDA编程的入门与实践 线程及同步二_第1张图片

        GPU有一级和二级缓存(即L1缓存和L2缓存)。常量内存则是用于存储常量和内核参数之类的只读数据。最后,存在纹理内存,这种内存可以利用各种2D和3D的访问模式。 

二、全局内存

        所有的块都可以对全局内存进行读写。该存储器较慢,但是可以从你的代码的任何地方进行读写。缓存可加速对全局内存的访问。所有通过cudaMalloc分配的存储器都是全局内存。

        使用全局内存示例

#include 
#define N 5

__global__ void gpu_global_memory(int *d_a)
{
	// “array”是指向设备上全局内存的指针
	d_a[threadIdx.x] = threadIdx.x;
}

int main(int argc, char **argv)
{
	// 定义主机数组
	int h_a[N];
	// 定义设备指针	
	int *d_a;       
						
	cudaMalloc((void **)&d_a, sizeof(int) *N);
	// 现在将数据从主机内存复制到设备内存 
	cudaMemcpy((void *)d_a, (void *)h_a, sizeof(int) *N, cudaMemcpyHostToDevice);
	// 运行kernel 
	gpu_global_memory << <1, N >> >(d_a);  
	// 将修改后的阵列复制回主机内存
	cudaMemcpy((void *)h_a, (void *)d_a, sizeof(int) *N, cudaMemcpyDeviceToHost);
	printf("Array in Global Memory is: \n");
	//Printing result on console
	for (int i = 0; i < N; i++) {
		printf("At Index: %d --> %d \n", i, h_a[i]);
	}
	
	return 0;
}

三、本地内存和寄存器堆

        本地内存和寄存器堆对每个线程都是唯一的。寄存器是每个线程可用的最快存储器。当内核中使用的变量在寄存器堆中装不下的时候,将会使用本地内存存储它们,这叫寄存器溢出。

        使用本地内存有两种情况:一种是寄存器不够了,一种是某些情况根本就不能放在寄存器中,例如对一个局部数组的下标进行不定索引的时候。基本上可以将本地内存看成是每个线程的唯一的全局内存部分。相比寄存器堆,本地内存要慢很多。虽然本地内存通过L1缓存和L2缓存进行了缓冲,但寄存器溢出可能会影响程序性能。

        使用寄存器的示例,代码中的t_local变量是每个线程局部唯一的,将被存储在寄存器堆中。用这种变量计算的时候,计算速度将是最快速的。

#include 
#define N 5

__global__ void gpu_local_memory(int d_in)
{
	int t_local;    
	t_local = d_in * threadIdx.x;     
	printf("Value of Local variable in current thread is: %d \n", t_local);
}



int main(int argc, char **argv)
{
	printf("Use of Local Memory on GPU:\n");
	gpu_local_memory << <1, N>> >(5);  
	cudaDeviceSynchronize();
	return 0;
}

四、高速缓冲寄存器

        较新的GPU上,每个流多处理器都含有自己独立的L1缓存,以及GPU有L2缓存。L2缓存是被所有的GPU中的流多处理器都共有的。所有的全局内存访问和本地内存访问都使用这些缓存,因为L1缓存在流多处理器内部独有,接近线程执行所需要的硬件单位,所以它的速度非常快。

        一般来说,L1缓存和共享内存共用同样的存储硬件,一共是64KB(注意:这是和计算能力有关,不一定共用相同的存储硬件,也不一定可以配置互相占用的比例,例如计算能力5.X和6.X的GPU卡就不能。同时L1缓存和共享内存在这两个计算能力上也不是共用的,但旧的计算能力和7.X GPU卡是如此),你可以配置L1缓存和共享内存分别在这64KB中的比例。所有的全局内存访问通过L2缓存进行。纹理内存和常量内存也分别有它们独立的缓存。

你可能感兴趣的:(计算机视觉,c++,cuda,并行处理,NVIDIA)