目录
本项目由以下四部分组成,本节是第3节:
3、MPI优化
4、OpenMP优化
MPI并行设计
在读取数据时使用串行,其余for循环都采用MPI并行。具体步骤如下:
1、 0进程读取数据文件,生成dataSet数组。
2、通过MPI_Scatterv()函数将dataSet数组分为多个长度不等的数据块,向各进程散射数据块。
3、各进程进行求和,通过MPI_Gather()函数将结果返回0进程累加,从而得出平均值。
4、0进程通过MPI_Bcast()函数将平均值(r)广播到所有进程。
5、各进程计算标准差的部分内容:。
6、0进程完成剩余的标准差计算得出标准差SD。
7、得到高斯分布的概率密度函数f(x)=[1/ sqrt(2*π*δ²)]*exp(-(x-μ)²/2δ²)
8、获得P(身高=170|女性)、P(身高=170|男性)、P(体重=60|女性)、P(体重=60|男性)等概率。
9、将相应的所有概率相乘,取最大值对应的特征为预测结果。
使用MPI_Scatterv散射大小不同的数据块
介绍MPI_Scatterv函数
本次实验使用MPI_Scatterv散射收发数据块,此方法不仅能解决广播占用内存开销大的问题,还能收发不同大小的数据块。在mpich_MPI_Scatterv可以查到MPI_Scatterv函数如下: int MPI_Scatterv(const void *sendbuf, const int *sendcounts, const int *displs,
MPI_Datatype sendtype, void *recvbuf, int recvcount,
MPI_Datatype recvtype, int root, MPI_Comm comm)
函数内的输入参数:
Sendbuf:数组指针,被散射发送的数组地址。
Sendcounts:整数数组,数组内每一个元素对应每个进程所发送的数据长度。
Displs:整数数组,数组内每一个元素对应每个进程从sendbuf收发数据的起始位置。
Sendtype:MPI数据类型,发送数据的数据类型。
Recvbuf:整数数组,接收分块数据到的数组。
Recvcount:整数,与Sendcounts对应,表示该进程所接受的数据长度。
Recvtype:MPI数据类型,接收数据的数据类型。
Root:整数,发送数据的进程,填散射数据的进程,一般填0。
Comm:通信子,通常填MPI_COMM_WORLD。
MPI_Scatterv参数选择
生成Sendcounts数组
Sendcounts数组是用来保存每个进程所接收的数据长度,数组的长度等于进程数,由于在MPI_Scatterv()传递的是数组指针,数组内每个数的内存地址要连续,可以用直接声明,也可以用malloc()函数来声明数组。
每个进程所分到的数据长度可以是不同的,本项目为了方便后面创建Displs数组,本次做法是让所有进程都接收(dataLen/comm_sz)个数据,最后一个进程再多接收(dataLen%comm_sz)个数据。
代码如下:
int *Sendcounts; //对每个进程分发的数据长度
Sendcounts = (int *) malloc(comm_sz * sizeof(int));//分配内存
for(