1.GPU与CPU
CPU:
1、为了尽量降低获取数据的延迟
2、更多的资源去控制逻辑
GPU:
1、为了做更多的高通量的并行计算
2、更多的资源去做计算
CPU有更大的缓存,能够一次性访问更多的数据,而GPU中计算单元占据着主导,通过高通量的数据吞吐,并行运算,达到甚至超越CPU的计算能力。
从上图可以看到CPU中每个线程相比之下等待数据的时间更少,而GPU通过多个线程的并行运行,从另一方面提高了计算速度。
2.GPU程序一般步骤
1.在GPU端分配内存空间
2.CPU传输数据给GPU
3.GPU做运算
4.GPU把计算结果传输回CPU
3.一个简单的GPU程序示例
#include <stdio.h>
#include "device_launch_parameters.h"
#include "cuda_runtime.h"
__global__ void HelloFromGPU(void)
{
printf("Hello World From GPU!\n");
}
int main(void)
{
printf("Hello World From CPU!\n");
HelloFromGPU <<<1, 5 >>> ();
cudaDeviceReset();
return 0;
}
函数前缀:
为__global__代表该函数在GPU上运行。
为__host__代表该函数在CPU上运行。
特殊的符号:
<<<x,y>>>
x代表grid中的block数。
y代表一个block的线程数。
运行结果:
可以看到CPU打印了1条语句,接着GPU打印了5条语句。
4. GPU的内存管理
三个函数:
cudeMalloc(void ** pointer, size_t nbytes)//内存分配
cudaMemset(void* pointer, int value, size_t count)//内存设置
cudaFree(void* pointer)//内存释放
一个例子:
int nbytes = 1024*sizeof(int)
int* d_a = 0;
cudaMalloc((void**)&d_a, nbytes);//创建了nbytes大小的内存空间
cudaMemset(d_a, 0, nbytes);//全部设置为0
cudaFree(d_a);//释放
5.GPU的拷贝函数
__host__cudaMemcpy(void*dst, void*src, size_t nbytes, cudaMemcpyKind direction)
Tips:1、该函数只有才copy完成后才会返回
2、在copy过程中会block CPU的线程
3、上一个CUDA命令执行完毕后才会开始copy
cudaMemcpyKind有如下类型 :
cudaMemcpyHostToDevice(从CPU到GPU)
cudaMemcpyDeviceToHost(从GPU到CPU)
cudaMemcpyDeviceToDevice(从GPU到GPU)
KUDA也提供了一个异步的拷贝函数,不会阻断CPU的执行:
cudaMemcpyAsync();
6. Share Memory与Global Memory
通常一个block会占用一个share memory,block中的线程均可以自由访问。
分配share memory:
__shared__ int a[SIZE]
而global memory是一个grid中共用的内存,线程访问的时候效率很低。