Skip to content

分布式高性能深度学习1月8日

lirui edited this page Jan 8, 2021 · 3 revisions

框架开发里面的kernel,实现的核心计算,需要在GPU上进行核心计算的一段代码。核心的操作封装在kernel里,针对不同硬件,进行不同的调度

并行计算常用技术(OpenMP/MPI/NCCL)

CUDA为主的并行方法,主要是针对GPU的,未来可以应用在并行多GPU,或者多机多卡这样的环境下

1、共享内存系统和分布式内存系统概述

笔记本、服务器等单机共享memory(共享内存)

多机情况(分布式内存系统),多个节点之间需要通过网络访问,会产生网络带宽的开销,计算过程中需要数据传输和发送,系统实现性能比较低,节奏会显著慢下来

network的组织方法,集合操作,算子,保证通信过程完成高并发计算过程

共享内存系统UMA,统一内存访问系统UMA系统或对称多处理器SMP,CPU地位平等,访问memory延时和距离是一样的,带宽受限memory control

共享内存系统NUMA:每一个CPU,和memory,多核多内存系统里面,interconnect,remote access,程序性能在带宽利用上有一个显著提升,一个核跑在CPU1上,但是操作系统做了一个上下文的切换,或者其它的一些操作,会导致它自动调度到CPU2上,但是memory还在CPU1的local memory上,导致程序与memory的通信要通过另外一个CPU

CPU亲和性,尽量给OS一个指令,在做上下文调度的时候,不要将程序从一个CPU挪到另一个CPU上

寄存器register,存储32/64字节buffer,memory是一个很慢的过程,memory内的东西放到寄存器内,速度会获得一个很高的提升

CPU上不同线程,或者线程内部有read访问,例如矩阵读取,一次性读多个数据,预期指令,提前取很多数据

UMA中受限于Memory Controller,NUMA中CPU有自己的Memory Controller,带宽可以扩展到之前的数倍

众核数据集,超算中心,GPU同样存在类似的问题

GPU升级会有peer to peer工具,硬件上有类似controller的控制单元,不需要GPU指令调度单元,批处理操作做读操作,GPU也有NUMA架构,有分组概念,同一台sever上的8块卡,可能1,2,3,4是一组,5,6,7,8是一组,组与组之间内部有一些id,组1和组2之间peer to peer访问都有差异,组间先保证性能达到最高,组内性能达到最高,然后再考虑数据传输的优化

CPU上每个核,多CPU之间,主频信息都是不一样的,主频高计算快,主频低功耗低,综合考虑各种频率

2、OPENMP技术(针对共享内存,用于CPU,多机多节点)

常规服务器上双路(2个CPU),每个CPU里面又是多核设计

Open Multi-Processing,开放多处理,主要是为共享式存储计算机上的并行程序设计使用,支持多平台共享存储器多处理器编程的C/C++和Fortran语言的规范和API

需要编译器支持:目前支持OpenMP的编译器包括:GCC(4.2+),ICC和VC(VC++ 2005+)

OpenMP提供对于并行描述的高层抽象,降低了并行编程的难度和复杂度

pthread.h

多线程机制,经常需要人工对任务进行切分,编程列写繁琐,OpenMP提供了更高级的API,可以使得在整个计算过程中可以更简练

OpenMP编程模型:OpenMP并行模型采用传统的fork-join模式,并行执行的控制流之间共享存储器。OpenMP程序单线程执行开始,在parallel伪指令调用处,主线程产生多个子线程

OpenMP缺点:1、不适合需要复杂的线程间同步、互斥及对线程做紧密控制的场合;2、不能很好地在非共享内存系统上使用。一个server上一个内存之间互访,无法直接用在并行多机这种环境下,指的是多机之间没有直接通过指令级互访,现在也有一些更高级的系统,node1和node2之间通过统一内存管理,会将这两块映射到同一块内存访问区间,address构建在同一地址空间中,这个时候也可以用OpenMP来做的,需要用特殊的软件,例如虚拟化来做这些事情。

OpenMP API构成

1、编译器伪指令:Pragma伪指令:通过标识引导编译器对相应代码段做处理,编译器根据指令自动将程序并行化,并加入同步互斥等通信手段。 eg. #pragma omp parallel (之后不能直接接大括号)

2、运行时函数:eg. int omp_get_num_threads();

3、环境变量:eg. export OMP_THREAD_LIMIT = 8

OpenMP常用指令:

parallel,用在一个代码段之前,表示这段代码将被多个线程并行执行

for,用于for循环之前,将循环分配到多个线程中并行执行,必须保证每次循环之间无相关性

parallel for,parallel和for语句的结合,也是用在一个for循环之前,表示for循环的代码将被多个线程并行执行

sections,用在可能会被并行执行的代码段之前

parallel sections,parallel和sections两个语句的结合

critical,用在一段代码临界区之前

single,用在一段只被单线程执行的代码之前,表示后面的代码段将被单线程执行

barrier,用于并行区内代码的线程同步,所有线程执行到barrier时要停止,直到所有线程都执行到barrier时才继续往下执行

atomic,用于指定一块内存区域被制动更新

master,用于指定一段代码块由主线程执行

ordered,用于指定并行区域的循环按顺序执行

threadprivate,用于指定一个变量是线程私有的

3、MPI技术(针对分布式内存系统,用于CPU,多机多节点)

4、Nvidia NCCL技术(针对GPU场景,集合通信操作,通信和计算技术)

Clone this wiki locally