中国海洋大学研究生并行计算参考答案-复习
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
中国海洋⼤学研究⽣并⾏计算参考答案-复习
⼀、名词术语翻译
1)SIMD :Single Instruction Multiple Data, 单指令多数据流。
2)MIMD :Multiple Instruction Multiple Data, 多指令多数据流。
3)SIMT :Single Instruction Multiple Threads, 单指令多线程。
4)SPMD :Single Program Multiple Data, 单程序多数据流。
5)MPMD :Multiple Program Multiple Data, 多程序多数据流。
6)PVP :Parallel Vector Processor, 并⾏向量处理机。
7)SMP :Symmetric Multiprocessor, 对称多处理机。
8)MPP :Massively Parallel Processor, ⼤规模并⾏处理机。
9)DSM :Distributed Shared Memory, 分布式共享存储。
10)COW :Cluster of Workstation, ⼯作站机群。
11)UMA :Uniform Memory Access, 均匀存储访问模型。
12)NUMA :Nonuniform Memory Access, ⾮均匀存储访问模型。
13)COMA :Cache-Only Memory Access, 全⾼速缓存访问模型。
14)NORMA :No-Remote Memory Access, ⾮远程存储访问模型。
15)CC-NUMA :Coherent-Cache Nonuniform Memory Access, ⾼速缓存⼀致性⾮均匀存储访问模型。
16)CUDA :Compute Unified Device Architecture, 统⼀计算架构。
17)GPU :Graphics Process Unit, 图形处理器。
18)GPGPU :General-Purpose Computing on GPU, 通⽤计算的图形处理器。
19)HPC :High Performance Computing, ⾼性能计算。
⼆、简答题
1、常⽤的MPI群集通信函数有哪些?简述其功能。
(4.5 P194)【群集通信是⼀个进程组中的所有进程都参加的全局通信操作。
群集通信⼀般实现三个功能:通信、聚集和同步。
通信功能主要完成组内数据的传输;
聚集功能在通信的基础上对给定的数据完成⼀定的操作;
同步功能实现组内所有进程在执⾏进度上取得⼀致。
】
(1)通信:
MPI_Bcast : ⼀对多⼴播同样的消息;
MPI_Gather : 多对⼀收集各个进程的消息;
MPI_Gatherv : MPI_Gather 的⼀般化;
MPI_Allgather : 全局收集;
MPI_Allgatherv : MPI_Allgather 的⼀般化;
MPI_Scatter :⼀对多散播不同的消息;
MPI_Scatterv : MPI_Scatter 的⼀般化;
MPI_Alltoall:多对多全局交换消息;
MPI_Alltoallv : MPI_Alltoall 的⼀般化。
(2)聚集:
MPI_Reduce_scatter : MPI_Reduce 的⼀般化;
MPI_Scan : 扫描。
(3)同步:
MPI_Barrier : 路障同步。
2.MPI点对点通信有哪四种模式?简述其特点。
(4.4 P183)
通信模式指的是缓冲管理,以及发送⽅和接收⽅之间的同步⽅式。
MPI点对点通信有如下四种模式:
(1)同步通信模式:只有相应的接收过程已经启动,发送过程才正确返回。
因此,同步发送返回后,表⽰发送缓冲区中的数据已经全部被系统缓冲区缓存,并且已经开始发送。
当同步发送返回后,发送缓冲区可以被释放或者重新使⽤。
(2)缓冲通信模式:缓冲通信模式的发送不管接收操作是否已经启动都可以执⾏。
但是需要⽤户程序事先申请⼀块⾜够⼤的缓冲区,通过MPI_Buffer_attch实现,通过MPI_Buffer_detach来回收申请的缓冲区。
(3)标准通信模式:是否对发送的数据进⾏缓冲由MPI的实现来决定,⽽不是由⽤户程序来控制。
发送可以是同步的或者缓冲的,取决于实现。
(4)就绪通信模式:发送操作只有在接收进程相应的接收操作已经开始才进⾏发送。
当发送操作启动⽽相应的接收还没有启动,发送操作将出错。
就绪通信模式的特殊之处就是接收操作必须先于发送操作启动。
3.简述OpenMP中private、threadprivate、firstprivate、lastprivate⼦句的区别。
(P11)
(1)private⼦句:
⽤于将⼀个或多个变量声明成线程私有的变量,变量声明成私有变量后,指定每个线程都有它⾃⼰的变量私有副本,其他线程⽆法访问私有副本。
即使在并⾏区域外有同名的共享变量,共享变量在并⾏区域内不起任何作⽤,并且并⾏区域内不会操作到外⾯的共享变量。
(2)thread private⼦句:
⽤来指定全局的对象被各个线程各⾃复制了⼀个私有的拷贝,即各个线程具有各⾃私有的全局对象。
threadprivate和private的区别在于threadprivate声明的变量通常是全局范围内有效的,⽽private声明的变量只在它所属的并⾏构造中有效。
(3)firstprivate⼦句:
private声明的私有变量不能继承同名变量的值;firstprivate⼦句可以继承原有共享变量的值。
(4)lastprivate ⼦句:
private 和firstprivate ⼦句在退出并⾏区域时都没有将私有变量的最后取值赋给对应的共享变量,lastprivate ⼦句就是⽤来实现在退出并⾏区域时将私有变量的值赋给共享变量。
4.OpenMP中schedule⼦句⽀持的三种任务调度⽅式是什么?简述其特点。
Schedule⼦句⽀持的三种任务调度⽅式是:static、dynamic、guided.
(1)静态调度(static)
当 parallel for 编译指导语句没有带schedule⼦句时,⼤部分系统中默认采⽤static调度⽅式。
假设有n次循环迭代,t个线程,那么给每个线程静态分配⼤约n/t次迭代计算。
n/t不⼀定是整数,因此实际分配的迭代次数可能存在差1的情况,如果指定了size参数,可能相差⼀个size。
静态调度时可以使⽤/不使⽤size参数。
不使⽤size参数:分配给每个线程n/t次连续的迭代。
使⽤size参数:分配给每个线程size次连续的迭代计算。
(2)动态调度(dynamic)
动态调度是动态地将迭代分配到各个线程,动态调度可以使⽤/不使⽤size参数。
不使⽤size参数:将迭代逐个地分配到各个线程;使⽤size参数:每次分配给线程的迭代次数为指定的size次。
(3)guided调度(guided)
guided调度是⼀种采⽤指导性的启发式⾃调度⽅法。
开始时每个线程会分配到较⼤的迭代块,之后分配到的迭代块会逐渐递减。
迭代块的⼤⼩会按指数级下降到指定的size⼤⼩,如果没有指定size参数,那么迭代块⼤⼩最⼩会降到1。
5.简述CUDA的线程结构与GPU硬件层次结构的对应关系。
线程的CUDA 层次结构映射到GPU 上处理器的层次结构:⼀个GPU 执⾏⼀个或多个Grid;Grid调度线程块block在流多处理器SM(Stream
可以实现同步。
线程块⽹格中的线程块的发射也是不确定的,且块之间没有同步机制,在⽹格执⾏期间,同⼀⽹格的两个不同线程块中的线程⽆法通过全局内存互相通信。
6、CUDA设备端有哪六种存储器模型?简述其特点。
CUDA设备有如下六种存储器模型:寄存器(register)、共享存储器(shared memory)、全局存储器(global memory)、局部存储器(local memory)、常数存储器(constant memory)、纹理存储器(texture memory)。
三、并⾏程序设
⽤MPI和OPENMP并⾏编程计算“累加和”和“π的近似值”(MPI-累加和,MPI-pi
近似值,openmp-累加和,openmp-pi近似值,⽼师说四选⼆)
1.Openmp-累加和
#include
const int N=100;
void main()
{
int sum = 0;
#pragma omp parallel for reduction(+:sum)
for(int i=1;i<=N;i++)
sum += i;
print("Result of adding 1 to %d is : %d", N,sum);
//openmp-π
#include
#include
#include
#define N 100000
void main( )
{
double sum = 0.0, pi, w, temp = 0.0;
int i;
w = 1.0 / N;
#pragma omp parallel for reduction(+:sum)private(x) for (i = 0; i < N; i ++) {
temp = (i + 0.5) * w;
sum= 4.0 / (1 + temp*temp) + sum;
}
printf("PI = %0.9f\n ", pi * w);
}
3.mpi-π
#include "mpi.h"
#include
#include
#define N 100000
void main(int argc, char* argv[])
{
double sum = 0.0, pi, w, temp = 0.0;
int i, myid, NumProc;
w = 1.0 / N;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &myid);
MPI_Comm_size(MPI_COMM_WORLD, &NumProc);
for (i = myid; i < N; i += NumProc)
{
temp = (i + 0.5) * w;
sum= 4.0 / (1 + temp*temp) + sum;
}
MPI_Reduce(∑, π, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); if (myid == 0)
{
printf("PI = %0.9f\n ", pi * w);
}
4.mpi-sum
#include "mpi.h"
#include
#include
#define N 100
void main(int argc, char* argv[])
{
int sum = 0,result;
int i, myid, NumProc;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &NumProc);
MPI_Comm_rank(MPI_COMM_WOLD, &myid);
for (i = myid; i <= N; i += NumProc)
{
sum += i;
}
MPI_Reduce(∑, &result, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD); if (myid == 0)
{
printf("sum of 1 to %d is: %d\n", N, result);
}
MPI_Finalize();
}。