Chapter 1 基于CUDA的异构并行计算
赵盛 最后更新时间 12/27/2018 2:31 PM
Ⅰ. 并行计算
1.1 什么是并行计算?
即一个大的计算问题被划分为很多可以同时解决的小问题。
1.2 什么是数据相关性?
一个程序应该包含两个基本的组成部分:指令和数据。当一个指令处理上一个指令产生的数据时,就有了数据相关性(依赖性)的概念。
数据相关性是限制并行性的主要因素。
1.3 什么是数据并行?
即同时处理许多数据。数据并行处理可以将数据映射给并行线程。
1.4 如何把数据依据线程进行划分?
块划分 block partitioning:一组连续的数据组成一个数据块,一个线程在同一时间通常只处理一个数据块。数据块以任意次序安排给一个线程。
周期划分 cyclic partitioning:一个数据块可能只包含一组连续数据中的一部分,数据块按周期排列,相邻线程处理相邻数据块,每个线程可以处理多个数据块。线程选择一个新块意味着要跳过和现有线程一样多的数据块。
块划分和周期划分的选择与计算机架构有关。
1.5 什么是弗林分类法 Flynn’s Taxonomy:
一种广泛使用的计算机架构分类方法:
1.6 什么是SIMD(单指令多数据)架构?
SIMD是一种并行架构,指具有多个核心的计算机,在任何时间点所有核心只有一个指令流处理不同数据流。(向量机是一种典型SIMD计算机)
SIMD的最大优势在于,在cpu上编写代码,程序员可以继续按照串行逻辑思考但对并行数据操作实现并行加速,其他细节由编译器来负责
1.7 一些量化变量?
延迟:衡量完成一次操作的时间,用微秒表示。
带宽:衡量单位时间内可以处理的数据量,用MB/s或GB/s表示。
吞吐量:衡量单位时间内成功处理的运算(操作)数量,用gflops(每秒十亿次浮点运算数量)表示。
1.8 通过内存组织方式划分计算机架构?
分布式内存的多节点系统:大型计算引擎由许多通过网络连接的处理器构成,每个处理器具有独立的本地内存,彼此通过网络通信,这通常被称为集群。
共享内存的多处理器系统:即大小在双处理器到上百处理器之间。这些处理器要么是与一个物理内存相关联,要么公用一个低延迟链路(PCIE)。尽管共享内存意味着共享地址空间,但并不意味着它就是一个独立的物理内存。
1.9 什么是GPU众核系统?
GPU几乎包括了前文所述所有并行结构,NVIDIA将其定义为SIMT(单指令多线程)架构。
1.10 简单区分CPU核心和GPU核心?
CPU核心少但重,用来处理非常复杂的控制逻辑,以优化串行程序。
GPU核心多但轻,由于优化简单控制逻辑的数据并行任务,注重数据吞吐。
即两头公牛和1024只小鸡的故事。
Ⅱ. 异构计算
2.1 同构计算和异构计算的区别?
同构计算使用的是同一架构下的一个或多个处理器执行一个应用
异构计算使用一个处理器架构来执行一个应用。为应用(任务)选择适合的架构,最终对性能有所改进。
2.2 什么是异构架构?
一个典型的异构计算节点包括两个多核CPU插槽和多个众核GPU。GPU不是一个独立运行平台而是CPU的协同处理器。GPU必须通过PCIE总线和CPU相连。异构架构中CPU被称为主机端,GPU被称为设备端。
CPU和GPU具有功能上的互补性,两者有效结合能使应用程序获得最佳运行效果。为此NVIDIA设计CUDA来支持CPU-GPU异构系统。
2.3 什么是异构应用?
一个异构应用包括两个部分:主机代码(CPU)和设备代码(GPU)。
异构应用通常由CPU初始化。这设备端加载计算密集型任务之前,CPU代码负责管理设备端的环境,代码和数据。
在计算密集型应用中,往往有很多并行数据的程序段,GPU用来提高这些并行数据的执行速度。
2.4 用来描述GPU的量化变量
描述GPU容量的指标:CUDA的核心数,内存大小。
评估GPU性能的指标:峰值计算性能(GFlops),内存带宽(GB/s)。
另外NVIDIA使用“计算能力“ compute capability来描述GPU的硬件性能。
2.5 用GPU输出Hello World
一般情况下,在CPU中运行的helloworld程序如下:
#include <stdio.h> int main(){ printf(“hello world from CPU!\n”); }
而在GPU中运行,首先需要编写内核函数
__global__ void helloFromGpu() { printf("hello world from GPU!\n"); }
修饰符__global__告诉编译器这个函数会从CPU中被调用,然后在GPU上被执行。
用helloFromGpu << <1, 10 >> > ()启动10个线程执行内核函数,所有线程执行相同代码。
函数cudaDeviceReset();用来显式释放和清空当前进程中与设备有关的所有资源
完整代码如下
#include "cuda_runtime.h" #include "device_launch_parameters.h" #include <stdio.h> __global__ void helloFromGpu() { printf("hello world from GPU!\n"); } int main() { helloFromGpu << <1, 10 >> > (); cudaDeviceReset(); return 0; }
运行结果:
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!
2.6 CUDA的编程结构(流程)
- 分配GPU内存。
- 从CPU内存拷贝数据到GPU内存。
- 调用CUDA内核函数完成运算。
- 将数据从GPU拷贝回CPU内存。
- 释放GPU内存空间。