并行处理简介
前言
本文为《CUDA与TensorRT部署学习笔记》系列中并行处理与GPU体系架构篇。本文主要从串行处理与并行处理的区别、并行处理的概念、常见的并行处理维度进行学习记录。
Goal:理解并行处理的基本概念,理解SIMD,以及编程中常见的并行处理方式。
1 串行处理与并行处理的区别
1.1 Sequential processing(串行)
1.1.1 定义
串行是指任务按照顺序一个接一个地执行,每个任务的开始必须等到前一个任务结束。
1.1.2 必须串行的两种情况
(1)数据依赖(Data Dependency)
数据依赖指的是一个计算任务需要依赖于另一个计算任务的结果。如果一个任务的输出作为另一个任务的输入,那么它们之间存在数据依赖。
(2)分支程序(Branching)
分支程序是指在程序执行过程中基于某些条件选择不同的执行路径。这通常涉及条件语句(如 if-else 语句)。
备注:为什么以下必须串行?
(1)数据依赖(Data Dependency)
- 顺序执行: 如果任务 A 的结果需要作为任务 B 的输入,那么在执行时,必须先执行 A,然后才能执行 B。这是因为 B 需要 A 的输出,如果并行执行,就无法确保 A 已经完成。
- 避免竞态条件: 并行执行可能导致竞态条件,即两个任务同时访问共享的数据,而其中一个任务可能会在另一个任务完成之前修改数据,导致不确定的结果。
(2)分支程序(Branching)
- 逻辑决策: 在分支程序中,不同的分支路径可能基于某些条件做出逻辑决策。如果并行执行,就需要同时执行所有分支,这可能导致不确定的执行结果。
- 避免竞态条件: 并行执行不同的分支可能会导致竞态条件,因为分支可能会影响共享的状态或资源。
1.2 Parallel processing(并行)
1.2.1 定义
并行是指多个任务同时执行,彼此独立进行。在并行执行中,不同的任务可以在同一时刻进行,相互之间没有直接的依赖关系。
1.2.2 一般涉及到并行的环节
(1)Loop parallelization
比如:在图像处理/深度学习中很多地方都是用到了循环。
-
pre/post process (前处理后处理)
- resize, crop, blur, bgr2rgb, rgb2gray, dbscan, findCounters
-
DNN中的卷积(convolution layer)以及全连接层(Fully connected layer)
(2)Image processing and DNN
比如:双线性插值、卷积层、全连接层等
备注
(1)不同编程语言的默认的ordering是不同的:
- row major: C/C++/Objective-C, Pascal, C#
- column major: Fortran, OpenGL, MATLAB, R, Julia
大白话理解
串行处理就像是一个人做事,他只能做一件事,直到他做完这件事才能开始做下一件事。这样,他的效率就比较低。
并行处理就像是多个人一起做事,每个人可以做一件不同的事。这样,他们的效率就会提高。
2 并行处理的概念
2.1 基本概念
- 指令/代码块同时执行
- 充分利用multi-core(多核)的特性,多个core一起去完成一个或多个任务。
- 并行是指同时进行的意思。并行是指同时处理多个任务或数据的技术。
2.2 容易混淆几个概念
2.2.1 并行和并发
(1)并行(Parallelism)
-
定义:并行是指两个或多个任务同时执行的能力。在并行计算中,多个处理单元同时执行多个任务,每个任务在独立的处理单元上执行,彼此之间互不干扰。
-
例子:比如,一个计算机程序分解为多个子任务,这些子任务同时在多个处理器上执行。这可以显著提高程序的执行速度。
-
比喻:可以将并行比喻为一条宽而大的高速公路,多个车辆(任务)可以同时行驶,互不影响。
(2)并发(Concurrency)
-
定义:并发是指两个或多个任务在重叠的时间段内执行的能力。在并发计算中,多个任务在同一时间段内交替执行,可能会在时间轴上重叠,但并不一定同时执行。
-
例子:多个任务在同一处理器上交替执行,每个任务都有一段时间片(时间段),它们的执行顺序可能是交织的。
-
比喻: 可以将并发比喻为一条狭窄但繁忙的道路,多个车辆(任务)依次行驶,可能会发生交替的情况。
(3)总结区别
-
关键区别:并行是真正的同时执行,而并发是在一段时间内交替执行。
-
硬件需求:并行通常需要多个处理单元,如多核处理器或多台计算机;而并发可以在单个处理器上通过时间片轮转实现。
-
性能提升:并行通常能够更显著地提高性能,因为多个任务可以同时执行;而并发的性能提升可能受限于处理器的性能和任务的切换开销。
-
复杂性:并行通常涉及更复杂的编程和同步机制,因为需要处理多个任务之间的数据共享和同步;而并发相对简单,因为任务之间的交替通常通过时间片轮转来管理。
2.2.2 进程和线程
(1)进程
-
定义: 进程是操作系统中的一个独立的执行单位,拥有独立的内存空间、文件句柄和系统资源。每个进程都有自己的地址空间,数据段、堆栈段等都是独立的。
-
特点:进程之间相互独立,一个进程的崩溃不会影响其他进程的稳定性。
-
创建和销毁:创建和销毁进程通常比较耗费资源,因为每个进程都有自己的资源和环境。
(2)线程
-
定义:线程是进程中的一个执行单元,是进程的一个子集。线程共享进程的内存空间和资源,但拥有独立的执行流。一个进程可以包含多个线程。
-
特点:线程之间共享进程的资源,因此线程的创建和上下文切换比进程要轻量级。线程的崩溃可能会影响整个进程的稳定性。
-
优势:线程之间的通信更容易,因为它们共享相同的地址空间,而无需特殊的通信机制。
(3)进程和线程的关系
-
包含关系:一个进程可以包含多个线程,但一个线程只能属于一个进程。
-
资源共享:进程中的线程可以共享进程的资源,包括内存、文件、I/O等。
-
独立性:线程之间是相对独立的,每个线程都有自己的执行序列。
(4)进程和线程的区别
| 特征 | 进程 | 线程 |
|---|---|---|
| 资源分配 | 独立 | 共享 |
| 执行单元 | 独立 | 并发 |
| 调度单位 | 进程 | 线程 |
(5)总结
进程的优势在于独立性和资源的隔离,劣势在于调度效率低。线程的优势在于调度效率高,劣势在于资源共享导致的竞争和冲突。
2.2.3 多核和加速比
(1)多核(Multi-core) :
-
定义:多核指的是在一个 CPU 芯片上集成多个独立的处理核心。这样的设计可以让计算机系统同时执行多个任务,每个核心独立执行指令,从而提高整体的处理能力。
-
特点:多核处理器可以在同一时间执行多个线程或进程,从而实现并行计算。
-
优势:相比单核处理器,多核处理器在处理多任务、多线程和并行计算时表现更为出色。
(2)加速比(Speedup) :
-
定义:加速比是衡量并行计算效果的指标,它表示在使用多个处理单元(如多核处理器)相对于使用一个处理单元时的性能提升倍数。
-
计算:加速比(Speedup)可以用以下公式表示:
Speedup=单核执行时间/多核执行时间 -
例子:如果一个任务在单核处理器上花费了10秒,在四核处理器上花费了2秒,那么加速比为 10/2=5 倍。
(3)关系:
-
多核处理器的存在使得并行计算更为容易实现。通过将任务分配给不同的核心,可以同时处理多个子任务,从而加速整体计算过程。
-
加速比是衡量多核处理器性能提升的一种方式。如果一个任务在多核处理器上能够以更短的时间完成,那么加速比将大于1,表示性能有所提升。
-
然而,并不是所有任务都能够实现理想的线性加速比(意思是双核的加速不一定是单核的两倍。双核的有时加速比也会比四核的快)。有些任务可能存在限制,使得加速比达不到处理器核心数的线性倍数。这可能是因为任务之间存在依赖关系、通信开销或者其他因素。
3 常见的并行处理
3.1 研究并行处理的方向很多
- 编译器自动化并行优化
GCC, LLVM, TVM, ... - 针对For循环的并行优化
tile, fuse, split, vectorization, ... - 计算图优化
CFG, HTG, MTG, ... - 数据流
Dataflow compiler
Dataflow architecture - Polyhedral
Polyhedral compiler - HPC
High performance computing
...
3.2 重点方向
3.2.1 SIMD
SIMD(Single Instruction, Multiple Data) 是一种计算机处理器的并行计算架构,其中一条指令可以同时操作多个数据元素。这种架构主要用于加速对大规模数据集进行相同操作的任务。
在CUDA编程与TensorRT中,以及NVIDIA中的tensor core的设计理念中都存在着SIMD。
CUDA编程中是使用的是SIMT(Single Instruction Multiple Thread),跟SIMD很相像,是SIMD的高级版。
大白话理解
你有一篮子相同的水果需要洗,SIMD 就像是你有很多只手,一下子就能同时处理这一篮子水果。这样,一条指令就能告诉所有的手同时进行同样的操作,加速了整个洗水果的过程。这就是 SIMD,通过一条指令同时操作多个数据,提高了计算速度。
3.2 在模型部署中比较常见的方法
3.2.1 CPU上的并行处理
- OpenMP
- pthread
- MPI
- Halide
(应用场景:图像预处理/后处理,Multi-task模型)
3.2.2 GPU上的并行处理
- CUDA programming
(应用场景:DNN优化)
3.2.3 做模型部署需要考虑的点
异构架构上时会有多种核,模型部署时,要考虑怎么在GPU上更快,考虑怎么与CPU进行通讯、DSP等等。会考虑得更多~!