Advertisement
Guest User

Task 4

a guest
Jan 21st, 2020
117
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.05 KB | None | 0 0
  1. #include "mpi.h"
  2. #include <iostream>
  3. #include <time.h>
  4. #include <cmath>
  5.  
  6. using namespace std;
  7.  
  8. struct ProcessorData {
  9.     int N, H;
  10.     int rank, size;
  11.  
  12.     float *M;
  13.  
  14.     ProcessorData(int N1, int H1, int rank1, int size1): N(N1), H(H1), rank(rank1), size(size1) {
  15.         // инициализируем рандом
  16.         int stime = (unsigned int)time(NULL) / (rank + 1);
  17.         srand(stime);
  18.  
  19.         // задаем случайную матрицу
  20.         M = new int[H * N];
  21.         for (int i = 0; i < H * N; i++)
  22.             M[i] = rand();
  23.     }
  24.  
  25.     void SwapMax() {
  26.         int center;
  27.         float max_above, max_below;
  28.         float max_above_t, max_below_t;
  29.         int max_above_row, max_below_row;
  30.  
  31.         // вычисление шлобального номера строки, чтобы понять где диагональный элемент
  32.         center = H * rank;
  33.  
  34.         // начальные значения саксимумов
  35.         max_above = M[0 + center + 1];
  36.         if (rank != 0)
  37.             max_below = M[0];
  38.         else
  39.             max_below = M[N];
  40.  
  41.         // номера строк (локальные), в которых лежат максимумы
  42.         max_above_row = 0;
  43.         max_below_row = 0;
  44.  
  45.         // поиск максимумов над и под диагональю
  46.         for (int i = 0; i < H; i++) {
  47.             for (int j = 0; j < center; j++)
  48.                 if (max_below <= M[i * N + j]) {
  49.                     max_below = M[i * N + j];
  50.                     max_below_row = i;
  51.                 }
  52.             for (int j = center + 1; j < N; j++) {
  53.                 if (max_above <= M[i * N + j]) {
  54.                     max_above = M[i * N + j];
  55.                     max_above_row = i;
  56.                 }
  57.             }
  58.             center += 1;
  59.         }
  60.  
  61.         // переход к глобальным номерам строк
  62.         max_below_row += H * rank;
  63.         max_above_row += H * rank;
  64.  
  65.         // поиск общих максимумов
  66.         MPI_Allreduce(&max_below, &max_below_t, 1, MPI_FLOAT, MPI_MAX, MPI_COMM_WORLD);
  67.         MPI_Allreduce(&max_above, &max_above_t, 1, MPI_FLOAT, MPI_MAX, MPI_COMM_WORLD);
  68.  
  69.         // если у данного процесса нет максимума, его макс строка "исключается"
  70.         if (max_above < max_above_t)
  71.             max_above_row = -1;
  72.         if (max_below < max_below_t)
  73.             max_below_row = -1;
  74.  
  75.         // поиск наибольших номеров строк, содержащих максимумы (на случай если максимумов несколько)
  76.         MPI_Allreduce(MPI_IN_PLACE, &max_above_row, 1, MPI_INT, MPI_MAX, MPI_COMM_WORLD);
  77.         MPI_Allreduce(MPI_IN_PLACE, &max_below_row, 1, MPI_INT, MPI_MAX, MPI_COMM_WORLD);
  78.  
  79.         if (max_above_row / H == max_below_row / H) {       // оба максимума лежат среди строк, доступных одному процессу
  80.             if (max_above_row != max_below_row) {           // и при этом лежат в разных строках
  81.                 float tmp;
  82.                 max_above_row -= H * rank;
  83.                 max_below_row -= H * rank;
  84.  
  85.                 for (int i = 0; i < N; i++) {
  86.                     tmp = M[max_above_row * N + i];
  87.                     M[max_above_row * N + i] = M[max_below_row * N + i];
  88.                     M[max_below_row * N + i] = tmp;
  89.                 }
  90.             }
  91.         }
  92.         else {      // максимумы лежат в областях доступа разных процессов
  93.             int rank1 = max_above_row / H;
  94.             int rank2 = max_above_row / H;
  95.             float *sendbuf, *recvbuf;
  96.             MPI_Status stat;
  97.  
  98.             if (rank == rank1) {
  99.                 sendbuf = new float[N];
  100.                 recvbuf = new float[N];
  101.  
  102.                 // переход к локальным номерам строк
  103.                 max_above_row -= H * rank;
  104.  
  105.                 // перенос нужной строки в буффер отправки
  106.                 for (int i = 0; i < N; i++)
  107.                     sendbuf[i] = M[max_above_row * N + i];
  108.  
  109.                 // обмен с другим процессом
  110.                 MPI_Sendrecv(&sendbuf, N, MPI_FLOAT, rank2, 1, &recvbuf, MPI_FLOAT, rank2, 1, MPI_COMM_WORLD, &stat);
  111.  
  112.                 // перенос строки из буффера приема в матрицу
  113.                 for (int i = 0; i < N; i++)
  114.                     M[max_above_row * N + i] = recvbuf[i];
  115.             }
  116.             else if (rank == rank2) {   //здесь всё то же самое, но для второго процесса
  117.                 sendbuf = new float[N];
  118.                 recvbuf = new float[N];
  119.  
  120.                 max_below_row -= H * rank;
  121.  
  122.                 for (int i = 0; i < N; i++)
  123.                     sendbuf[i] = M[max_below_row * N + i];
  124.  
  125.                 // здесь тот же обмен, но номера процессов идут в другом порядке, чтобы передача/прием шли в обратную сторону
  126.                 MPI_Sendrecv(&sendbuf, N, MPI_FLOAT, rank1, 1, &recvbuf, MPI_FLOAT, rank1, 1, MPI_COMM_WORLD, &stat);
  127.  
  128.                 for (int i = 0; i < N; i++)
  129.                     M[max_below_row * N + i] = recvbuf[i];
  130.             }
  131.         }
  132.     }
  133. };
  134.  
  135. int main(int argc, char** argv) {
  136.     int N, H;
  137.     int rank, size;
  138.  
  139.     float *TM, *trecv;
  140.  
  141.     N = stoi(argv[1]);
  142.  
  143.     MPI_INIT(&argc, &argv);
  144.  
  145.     MPI_COMM_RANK(MPI_COMM_WORLD, &rank);
  146.     MPI_COMM_SIZE(MPI_COMM_WORLD, &size);
  147.  
  148.     H = N / size;
  149.  
  150.     ProcessorData pd(N, H, rank, size);
  151.  
  152.     pd.SwapMax();
  153.  
  154.     TM = new float[N*N];
  155.     MPI_Gather(pd.M, &TM, MPI_FLOAT, 0, MPI_COMM_WORLD);
  156.  
  157.     if (rank == 0) {
  158.         // У нас есть матрица. Что с ней делать дальше никто не сказал.
  159.     }
  160.  
  161.     MPI_Finalize();
  162.     return 0;
  163. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement