lastTest

学号:2019301110060 姓名:刘振平 院系:植物科学技术学院

1.二维数组乘积

#include "mpi.h"
#include "omp.h"
#include <malloc.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
  int rank, numprocess, dimension;
  double startTime, endTime;
  float *Matrix1;
  float *Matrix2;
  float *sendBuf, *revBuf;
  MPI_Init(&argc, &argv);
  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  MPI_Comm_size(MPI_COMM_WORLD, &numprocess);
  MPI_Barrier(MPI_COMM_WORLD);
  startTime = MPI_Wtime();
  if (rank == 0)
  {
    printf("请输入矩阵的维度·:\n");
    scanf("%d", &dimension);
    Matrix1 = (float *)malloc(dimension * dimension * sizeof(float));
    Matrix2 = (float *)malloc(dimension * dimension * sizeof(float));
    for (int i = 0; i < dimension; i++)
    {
      // srand(rank*i+1);
      for (int j = 0; j < dimension; j++)
      {
        Matrix1[i * dimension + j] = 100.0 * rand() / RAND_MAX;
        Matrix2[i * dimension + j] = 100.0 * rand() / RAND_MAX;
      }
    }
    revBuf = (float *)malloc(dimension * dimension * sizeof(float));
  }
  /*
    广播二维数组
    */
  MPI_Bcast(&dimension, 1, MPI_INT, 0, MPI_COMM_WORLD);
  MPI_Bcast(&Matrix1, dimension * dimension, MPI_FLOAT, 0, MPI_COMM_WORLD);
  MPI_Bcast(&Matrix2, dimension * dimension, MPI_FLOAT, 0, MPI_COMM_WORLD);
  sendBuf = (float *)malloc(dimension * sizeof(float));
  for (int i = rank; i < dimension; i += numprocess)
  {
    for (int j = 0; j < dimension; j++)
    {
      for (int k = 0; k < dimension; k++)
      {
        sendBuf[j] = Matrix1[i * dimension + k] * Matrix2[k * dimension + j];
      }
    }
    MPI_Gather(sendBuf, dimension, MPI_FLOAT, revBuf, dimension, MPI_FLOAT, 0, MPI_COMM_WORLD);
  }
  MPI_Barrier(MPI_COMM_WORLD);
  endTime = MPI_Wtime();
  if (rank == 0)
  {
    for (int i = 0; i < dimension; i++)
    {
      // srand(rank*i+1);
      for (int j = 0; j < dimension; j++)
      {
        printf("%f\t",revBuf[i*dimension+j]);
      }
      printf("\n");
    }
    printf("time= %g(s)\n", endTime - startTime);
  }

  free(Matrix1);
  free(Matrix2);
  MPI_Finalize();
  return 0;
}

2.计算数列加和值

2.1MPI模式

  • 根据进程数将N拆分成多个部分

2.2MPi+OpenMp模式

  • 根据进程ID拆分每个进程的计算范围

  • 在每个范围中使用多线程进行计算

2.3并行效率和加速比

取N=10000000000

线程数

时间

加速比

并行效率

1

5.42

1

1

2

5.36

1.01

0.505

4

5.54

0.97

0.2425

6

5.38

1.0

0.16

8

5.46

0.99

0.123

3.所有计算的PI

3.1OMP多线程计算PI

3.1.1PAD模式

  • PAD模式进行多线程计算PI,利用二维数组存储计算结果

  • 在多线程结束后,遍历数组获取对应的pi值

  • 防止了多线程在输入输出时,造成的阻塞

3.1.2并行域模式

  • 使用一维数组存储计算结果,所以会造成数据读写时的阻塞

3.1.3reduction 制导

  • 在并行域中,使用reduction制导语句将最终结果直接累加到sum变量

  • 省去了for循环的遍历,以及多个线程对数据的读写

3.2MPI多进程模式

  • 使用MPI_Scatter将要计算的范围分发给各个进行

  • 使用MPI_Gather将每个进程的结果汇总到0号进程

3.3MPI和OpenMPI混合模式

  • 根据进程ID计算每个进程所要计算的范围

  • 每个进行使用多线程进行计算,使用reduction制导语句将多个线程的结果汇总

  • 使用MPI_Reduce将多个进程的计算结果进行汇总

Last updated

Was this helpful?