标签: 并行计算
. | . |
---|---|
郑冬健 | [email protected] |
编号 | 更新时间 | 内容 |
---|---|---|
1 | 201606062144 | Openmp gcc 编译选项为-fopenmp |
2 | 201606062144 | 虚进程不能避免死锁,系理解错误 |
Memory Wall,内存性能提高不及CPU
处理器数 P ,问题规模 W (串行分量 Ws ),并行化部分 Wp ,串行时间 Ts ,并行时间 Tp ,加速比 S ,效率 E
比较 | 进程 | 线程 |
---|---|---|
调度 | 代价大 | 代价小 |
并发性 | 可以并发执行 | 也可以并发执行,并发性更好 |
拥有资源 | 拥有自己的资源 | 除部分必不可少的栈和寄存器,不拥有自己的资源 |
系统开销 | 创建和撤销要分配/回收资源,耗时大 | 线程切换只涉及少量寄存器的操作,不涉及存储管理方面的操作,切换较为容易 |
POSIX | func |
---|---|
pthread_cancel | 终止另一个线程 |
pthread_create | 创建一个线程 |
pthread_detach | |
pthread_equal | 测试TID相等 |
pthread_exit | |
pthread_join | |
pthread_self |
- pthread_mutex_t mtx
- pthread_mutex_init(&mtx, NULL);
- pthread_mutex_lock
pthread_mutex_unlock
- pthread_mutex_destroy
-popenmp
-fopenmp
#pragma omp parellel
标识并行程序块 子句 | 功能 |
---|---|
private | 列出的变量对每个线程私有 |
shared | 列出的变量为所有线程共享 |
default | ? |
firstprivate | 私有,且原子初始化 |
lastprivate | 私有,且原始变量由最后一次迭代的赋值所修改 |
reduction | 对列表中出现的变量进行归约 |
threadprivate | 使一个全局文件作用域的变量在并行域内编程每个线程私有。每个线程对该变量赋值一份私有拷贝。 |
copyin | 用来为线程组中所有线程的threadprivate变量赋相同的值 |
copyprivate | ? |
运行时库函数: omp.h
环境变量: OMP_SCHEDULE
, etc
MPI_COMM_WORLD
)接口 | 说明 |
---|---|
MPI_Init | MPI初始化,开始 |
MPI_Finalize | MPI结束 |
MPI_Comm_size | 获取通信域内进程数量 |
MPI_Comm_rank | 获取当前进程的编号 |
MPI_Send | 发送消息(数据) |
MPI_Recv | 接收消息(数据) |
MPI_COMM_WORLD
MPI_Comm_split(MPI_Comm comm, int color, int key, MPI_Comm* newcomm)
创建一个通信域。color
用来划分处理器。前缀 | 含义 |
---|---|
- | 标准通信模式 |
B | 缓存通信模式 |
S | 同步通信模式 |
R | 就绪通信模式 |
通信模式 | 说明 |
---|---|
标准通信模式 | MPI_Send 同步发送( → 死锁)、异步发送 |
缓存通信模式 | MPI_Bsend ,用户自己管理缓冲区 |
同步通信模式 | 本身不依赖接收是否已经启动,但MPI_Ssend 同步发送必须等到接收进程开始后才能正确返回。返回时说明数据已经全部进入缓冲,刚开始发送 |
就绪通信模式 | MPI_Rsend 只有当接收进程的接收操作已经启动时,才可以在发送进程启动发送操作 |
前缀 | 含义 |
---|---|
- | 标准通信模式 |
B | 缓存通信模式 |
S | 同步通信模式 |
R | 就绪通信模式 |
通信模式 | 发送 | 接收 |
---|---|---|
标准通信模式 | MPI_Isend ,立即返回 |
MPI_Irecv |
缓存通信模式 | MPI_Ibsend |
- |
同步通信模式 | MPI_Issend |
- |
就绪通信模式 | MPI_Irsend |
- |
重复非阻塞通信模式 | MPI_Send_init MPI_Bsend_init 等 |
- |
重复非阻塞通信模式用于需要重复进行通信的情形,如一个for循环内部。
非阻塞通信的完成与检测
MPI_Test
、MPI_Testany
、MPI_Testsome
、MPI_Testall
MPI_Wait
、MPI_Waitany
、MPI_Waitsome
、MPI_Waitall
int right_rank = rank == max_rank ? 0 : rank + 1;
int left_rank = rank == 0 ? max_rank : rank - 1;
MPI_Issend(data, count, MPI_DOUBLE, right_rank, tag1, MPI_COMM_WORLD);
MPI_Irecv(buffer, count, MPI_DOUBLE, left_rank, tag2, MPI_COMM_WORLD);
MPI_Wait...
MPI_Sendrecv(
void* sendbuf,
int sendcount,
MPI_Datatype sendtype,
int dest,
int sendtag,
void* recvbuf,
int recvcount,
MPI_Datatype recvtype,
int source,
int recvtag,
MPI_Comm comm,
MPI_Status* status
)
MPI_PROC_NULL
定义为整数-2
,不会和正常的编号( ≥0 )产生冲突,因此可以让MPI对其特殊处理。if (myrank > 0) {
leftrank = myrank - 1;
} else {
leftrank = MPI_PROC_NULL;
}
//n是最大进程编号
if (myrank < n) {
rightrank = myrank + 1;
} else {
rightrank = MPI_PROC_NULL;
}
//数据向右平移
MPI_Sendrecv(send_data1, send_count, MPI_FLOAT, rightrank, tag1, recv_data1, recv_count, MPI_FLOAT, leftrank, tag1, MPI_COMM_WORLD, status);
//数据向左平移
MPI_Sendrecv(send_data2, send_count, MPI_FLOAT, leftrank, tag1, recv_data2, recv_count, MPI_FLOAT, rightrank, tag1, MPI_COMM_WORLD, status);
组通信类型 | |
---|---|
一到多, Broadcast,Scatter | 广播(bcast,发送消息给某一通信域内的所有进程),发散(scatter,向某一通信域内的所有进程发送一个不同的消息) |
多到一, Reduce,Gather | root进程接收各个进程(包括自己)的消息,通信连接按rank号进行。Reduce会进一步做归约处理(Max, Min, Sum等) |
多到多, Allreduce,Allgather,Alltoall | 每个进程都从其他进程接收消息。Reduce同上。Alltoall接发阵列 |
同步 , Barrier | 同步各进程 |
归约操作 | 功能 |
---|---|
Reduce | 归约到某一进程 |
Reduce_scatter | 归约并散发 |
Allreduce | 组归约,每个进程的缓冲区都得到相同的归约结果 |
Scan | 每个进程对排在前面的进程做归约 |
MPI数据类型 | 对应C/C++数据类型 |
---|---|
MPI_FLOAT | float |
… | … |
.
.
MPI调用 | 功能 |
---|---|
MPI_Cart_create |
创建虚拟拓扑 |
MPI_Cart_coords |
根据进程号返回笛卡尔坐标 |
MPI_Cart_rank |
根据笛卡尔坐标返回进程号 |
MPI_Cart_shift |
数据平移 |
MPI_Cart_sub |
划分子拓扑 |
编程模型
map
和reduce
map
:(in_key, in_value) -> (out_key, intermediate_value) list
reduce
: (out_key, intermediate_value list) -> out_value list
refer to: MapReduce技术的初步了解与学习
例子:求前缀和
PCAM步骤: 划分→通讯→组合→映射
划分:分解成小的任务,开拓并发性。
通讯:确定诸任务间的数据交换,检测划分的合理性。
OpenMP只需要知道基本的概念和能干什么即可,不用掌握编译制导语句
MPI需要掌握,重点
MapReduce:word count & 倒排索引 要搞清楚,词共现等不需要