MPI


MPI分布式内存编程技术

Fortran 77 是什么呀~~

  • 单个进程(process)
    • 拥有独立的执行环境
    • 独立地申请和占有内存空间
  • 单机内多个进程
    • 多个进程可同时存在在单机内同一个操作系统
    • 进程间相互独立,内存空间不相交
    • 进程间可以相互交换信息
  • 包含于通过网络链接的不同处理器的多个进程
    • 进程独立存在,需要通过一些接口函数来实现目前编程空间的需求
    • 物理隔离,不能越过内存,访问需要通过“复印“的操作

MPI重要概念

  • 进程序号(rank)的进程由进程组活通信器序号唯一确定
    • 也就是每个进程自己的名字
    • 同一个进程在不同的通信组或通信器之间可以有不同的序号
  • 消息(message)

MPI原始数据类型

MPI类型 C类型
MPI_CHAR signed char
MPI_SHORT signed short int
MPI_INT signed int
MPI_LONG signed long
MPI_UNSIGNED_CHAR unsigned char
MPI_UNSIGNED_SHORT unsigned short int
MPI_UNSIGNED unsigned int
MPI_UNSIGNED_LONG unsigned long int
MPI_FLOAT float
MPI_DOUBLE double
MPI_LONG_DOUBLE long double
MPI_BYTE
MPI_PACKED

MPI——BYTE(一个字节)

MPI_PACKED(打包数据)

MPI基本结构

MPI include file

变量定义

MPI 环境初始化

int MPI_Init(int *argc,char *argv[]);

int MPI_Init(NULL,NULL);

执行程序

进程间通信

退出``MPI`环境

int MPI_Finalize(void);

MPI基本函数

开始

终止

获取墙钟时间

double MPI_Wtime(void)

Sample Hello World

点对点通信

  • 定义

    • communicator(通信子,通信域) source destination 0
  • 阻塞式点对点通信

    • int MPI_Send(void *buf,int count,MPI_Datatype,int dest,int tag ,MPI_Comm comm);
      //count是指定数据类型的个数
      //dest范围是0~np-1,或MPI_PROC_NULL
      //tag范围是0~MPI_TAG_UB,用来区分消息
      
      
      - ```c
        int MPI_Recv(void *buf,int count,MPI_Datatype datatype,int source,int tag,MPI_Comm comm,MPI_Status *status);
        //count是接受缓冲区的大小,表示接受上界。
  • 编写安全的``MPI`程序

  • 非阻塞式点对点通信

int MPI_Isend(void* buf, int count, MPI_Datatype datatype, int dest, int tag,MPI_Comm COmm,MPI_Request *request);
/*
IN buf 发送缓冲区的起始地址
IN count 发送缓冲区的大小(发送元素个数)
IN datatype 发送缓冲区数据的数据类型
IN dest 月的进程的rank值
IN tag 消息标签
IN comm 通信空间/通信城
OUT request 非阳塞通信完成对象(句树)
MPI_Ibsend/MPI_Issend/MPI_Irsend:非阻塞缓冲模式/非阻赛同步模式/
*/
int MPI_Irecv(void* buf, int count, MPI_Datatype datatype, int source, int tag,MPI_Comm comm,MPI_Request* request);

并行计算优化技巧

编译优化

IPCC比赛环境:CPU AMD EPYC 7452

-O3-fopenmp -march=znver1 -mfma -fomit-frame-pointer -mavx2 -mtune=znever**……**

Cache 优化

//matrix multiplication
for(int i = 0; i < n; i++){
    for(int k = 0; k < n; k++){
        for(int j = 0;j < n; j++){
            c[i][j] += A[i][k] * B[k][j];
        }
    }
}
//ikj这个组合是最快,多重循环套一起,可以尝试将循环次序进行交换

SIMD

向量指令是一种并行计算技术,可以在一次指令中同时处理多个数据元素,从而提高计算效率。与传统的标量指令相比,向量指令能够耨将计算操作应用**……**

  • 使用条件
  • 最内层循环
  • 循环的长度是固定的
  • 循环体内没有变量依赖关系。 不然就不好进行
  • 循环访问的数据最好是连续的,或者最起码是相同的步长间隔
  • 循环体内没有复杂的分支判断
  • 循环内没有调用其他复杂的函数

查CPU手册

  • 对齐

  • 在C语言中可以使用aligned_alloc函数来申请对齐的内存。该函数的声明:

  • ……

  • 一个例子

    记得free

  • 边角料的处理 加一个非SIMD的处理

  • 内部处理

  • 外部处理

向量点乘

  • 手动/自动向量化
  • #pragma ivdep
  • #pragma vector aligned
  • #pragma vector
  • ** ……**

预取

__builtin_prefetch函数

……

  • 执行缓存预取操作。可以将制定地址的数据预取到cache中

Openmp task

TASK定义一个可以被任何线程执行的独立的工作单元

  • if:指定是否生成一个任务
  • final:制定是否将生成的任务和它的所有子任务都标记为final,即不可再分
  • ……

任务流

https://taskflow.github.io/

  • 一个例子

打比赛用不上

工程好用,cpu和gpu都可用

C++不支持异步程序

Qt是C++界面库,需要手动wait

排序

  • SortKey 排一个

  • SortPairs 排点对(结构体)

  • Std::sort

  • Omp task sort

  • __gnu_parallel::sort 网上的项目,开源库

  • parallel_radix_sort 开源的并行的基数排序

IPCC 2022初赛

支撑点切比雪夫距离和——SumDistance

k = 2,3,的情况

伪代码

……

  • j < i

PAC2019初赛

CFD 应用物理量梯度求解算法优化

PAC2019-初赛题

简介

计算流体力学程序中,粘性项离散的关键是计算物理量在界面处的梯度。求梯度的原理是高斯-格林公式:

$\oint_{V}\triangledown Q dV=\iint_{\partial V} Q \cdot\vec{n} dS$

即单元中心的梯度可以积分面心的值得到。

核心是将几个循环进行合并,然后将代码修改为编译器更容易优化的形式,关键还是使用omp来优化,当然对于这种计算比较原子操作而且数量大的操作使用cuda肯定也挺好的,lxc试了一下确实是这样的


文章作者: hugo
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 hugo !
  目录