并行计算:
本部分主要讲解并行的基础知识, 在前头的MPI & OpenMP并行编程基础基本掌握过了, 直接Pass
异构计算:
这里的内存带宽应该指的是显存带宽
CPU & GPU的选择:
有两个考量点:
- 并行性
- 数据规模
如果一个问题有较小的数据规模、复杂的控制逻辑和/或很少的并行性,那么最好选择CPU处理该问题,因为它有处理复杂逻辑和指令级并行性的能力。
如果该问题包含较大规模的待处理数据并表现出大量的数据并行性,那么使用GPU是最好的选择。因为GPU中有大量可编程的核心,可以支持大规模多线程运算,而且相比CPU有较大的峰值带宽。
CPU线程 & GPU线程:
CPU上的线程通常是重量级的实体。操作系统必须交替线程使用启用或关闭CPU执行通道以提供多线程处理功能。上下文的切换缓慢且开销大。
GPU上的线程是高度轻量级的。在一个典型的系统中会有成千上万的线程排队等待工作。如果GPU必须等待一组线程执行结束,那么它只要调用另一组线程执行其他任务即可。
CPU的核被设计用来尽可能减少一个或两个线程运行时间的延迟,而GPU的核是用来处理大量并发的、轻量级的线程,以最大限度地提高吞吐量。
CUDA 异构计算平台:
CUDA提供了两层API来管理GPU设备和组织线程,如图1-13所示。
-
CUDA驱动API
驱动API是一种低级API,它相对来说较难编程,但是它对于在GPU设备使用上提供了更多的控制。
-
CUDA运行时API
运行时API是一个高级API,它在驱动API的上层实现。每个运行时API函数都被分解为更多传给驱动API的基本运算。
二者在性能上没有明显差异, 相反, 使用者的程序架构对性能更有明显的影响
二者只能不能混用, 只能选择其一
大致的编译过程:
Hello World:
例程:
#include <stdio.h>
__global__ void helloFromGPU(void){
printf("Hello World from GPU!\n");
}
int main(){
helloFromGPU <<<1, 100>>> ();
cudaDeviceReset();
return 0;
}
-
__global__
修饰一个函数, 表示此函数会从CPU上调用, 并在GPU上执行
-
<<<>>>
表示从主线程到设备端(device)代码的调用, 尖括号内的参数表示执行配置, 指定开多少个线程执行函数
一个内核函数通过一组线程执行, 所有线程执行相同的代码(SIMD)
-
函数cudaDeviceRest()用来显式地释放和清空当前进程中与当前设备有关的所有资源
输出:
Hello World from GPU!
Hello World from GPU!
Hello World from GPU!
Hello World from GPU!
Hello World from GPU!
Hello World from GPU!
Hello World from GPU!
Hello World from GPU!
Hello World from GPU!
Hello World from GPU!