Advertisement
Guest User

Untitled

a guest
Dec 18th, 2018
72
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 7.89 KB | None | 0 0
  1. #define _GNU_SOURCE
  2. #include "mpi.h"
  3. #include <unistd.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <time.h>
  8. #include <math.h>
  9.  
  10.  
  11.  
  12. #define MATRIX_SIZE 10
  13. #define RANDOM_MAX 10
  14. #define RANDOM_MIN 0
  15.  
  16.  
  17. float myRand() {
  18.     return (float)(RANDOM_MIN + (rand() % (RANDOM_MAX - RANDOM_MIN + 1)));
  19. }
  20.  
  21.  
  22. int main(int argc, char** argv) {
  23.  
  24.     setbuf(stdout, NULL);
  25.     int err;
  26.     err = MPI_Init(&argc, &argv);
  27.  
  28.     int rank;
  29.     int size;
  30.  
  31.     err = MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  32.     err = MPI_Comm_size(MPI_COMM_WORLD, &size);
  33.  
  34.     //srand(time(NULL));
  35.  
  36.     ///   Buffer init
  37.     int layerSize;
  38.     MPI_Pack_size(MATRIX_SIZE, MPI_FLOAT, MPI_COMM_WORLD, &layerSize);
  39.     int bufferSize = 10 * (layerSize + MPI_BSEND_OVERHEAD);
  40.     char* buffer = (char*)malloc(bufferSize * sizeof(float));
  41.     MPI_Buffer_attach(buffer, bufferSize);
  42.  
  43.  
  44.     int colCnt = (MATRIX_SIZE + 1) / size;
  45.     int rest = (MATRIX_SIZE + 1) % size;
  46.     if(rank < rest) {
  47.         colCnt++;
  48.     }
  49.  
  50.     ///   Process that takes b
  51.     int procB = (MATRIX_SIZE + 1) % size - 1;
  52.     procB = procB < 0 ? size - 1 : procB;
  53.  
  54.     float columns[MATRIX_SIZE + 1][colCnt];
  55. //    float columns[colCnt][MATRIX_SIZE];
  56.  
  57.  
  58.     ///   Number of columns in each proc
  59.     int* counts = NULL;
  60.  
  61.  
  62.     if(!rank) {
  63.         counts = (int*)malloc(sizeof(int) * size);
  64.  
  65.         for(int i = 0; i < size; ++i) {
  66.             counts[i] = 0;
  67.         }
  68.  
  69.         ///   Generate random matrix
  70.         float A[MATRIX_SIZE][MATRIX_SIZE + 1];
  71.         //float b[MATRIX_SIZE];
  72.         for(int i = 0; i < MATRIX_SIZE; ++i) {
  73.             for(int j = 0; j < MATRIX_SIZE + 1; ++j) {
  74.                 A[i][j] = myRand();
  75.             }
  76.             //b[i] = myRand();
  77.         }
  78.  
  79.         ///   Print matrix
  80.         for(int i = 0; i < MATRIX_SIZE; ++i) {
  81.             for(int j = 0; j < MATRIX_SIZE; ++j) {
  82.                 printf("%.2f ", A[i][j]);
  83.             }
  84.             printf(" |  %.2f\n", A[i][MATRIX_SIZE]);
  85.         }
  86.  
  87.  
  88.         ///   Send cols
  89.         for(int i = 0; i < MATRIX_SIZE + 1; ++i) {
  90.             if(i % size) {
  91.                 float buffer[MATRIX_SIZE + 1];
  92.  
  93.                 for(int j = 0; j < MATRIX_SIZE; ++j) {
  94.                     buffer[j] = A[j][i];
  95.                 }
  96.                 buffer[MATRIX_SIZE] = i;
  97.  
  98.                 MPI_Bsend(&(buffer[0]), MATRIX_SIZE + 1, MPI_FLOAT, i % size,
  99.                           0, MPI_COMM_WORLD);
  100.                 counts[i % size]++;
  101.             }
  102.             else {
  103.                 for(int j = 0; j < MATRIX_SIZE; ++j) {
  104.                     columns[j][i / size] = A[j][i];
  105.                 }
  106.                 columns[MATRIX_SIZE][i / size] = i;
  107.             }
  108.         }
  109.     }
  110.     else {
  111.         /// Receive matrix
  112.         for(int i = 0; i < colCnt; ++i) {
  113.             float buffer[MATRIX_SIZE + 1];
  114.             MPI_Recv(&(buffer[0]), MATRIX_SIZE + 1, MPI_FLOAT, 0,
  115.                      0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
  116.             int j = buffer[MATRIX_SIZE] / size;
  117.  
  118.             for(int i = 0; i < MATRIX_SIZE + 1; ++i) {
  119.                 columns[i][j] = buffer[i];
  120.             }
  121.         }
  122.     }
  123.     int cnt = 0;
  124.     MPI_Barrier(MPI_COMM_WORLD);
  125.  
  126.  
  127.  
  128.     double startTime = MPI_Wtime();
  129.  
  130.  
  131.     ///   Forward pass
  132.     cnt = 0;
  133.     for(int i = 0; i < MATRIX_SIZE - 1; ++i) {
  134.         MPI_Barrier(MPI_COMM_WORLD);
  135.         if(i % size == rank) {
  136.             ///   Max finding
  137.             double max = 0;
  138.             int maxInd = 0;
  139.             for(int j = i; j < MATRIX_SIZE; ++j) {
  140.                 if(max < abs(columns[j][cnt])) {
  141.                     max = abs(columns[j][cnt]);
  142.                     maxInd = j;
  143.                 }
  144.             }
  145.  
  146.             int indices[2];
  147.             indices[0] = i;
  148.             indices[1] = maxInd;
  149.  
  150.             ///   Send swap to other processes
  151.             MPI_Bcast(&(indices[0]), 2, MPI_INT, i % size, MPI_COMM_WORLD);
  152.  
  153.             ///   Perform swaps
  154.             for(int l = 0; l < colCnt; ++l) {
  155.                 float swap = columns[indices[0]][l];
  156.                 columns[indices[0]][l] = columns[indices[1]][l];
  157.                 columns[indices[1]][l] = swap;
  158.             }
  159.  
  160.  
  161.             float coeffs[MATRIX_SIZE - i - 1];
  162.             ///   Subtracting
  163.             for(int j = i + 1; j < MATRIX_SIZE; ++j) {
  164.                 coeffs[j - i - 1] = -columns[j][cnt] / columns[i][cnt];
  165.                 columns[j][cnt] = 0;
  166.             }
  167.  
  168.  
  169.             ///   Send coefficients
  170.             for(int j = 0; j < size; ++j) {
  171.                 if(rank != j) {
  172.                     MPI_Bsend(&(coeffs[0]), MATRIX_SIZE - i - 1, MPI_FLOAT, j,
  173.                               0, MPI_COMM_WORLD);
  174.                 }
  175.             }
  176.             for(int j = cnt + 1; j < colCnt; ++j) {
  177.                 for(int k = i + 1; k < MATRIX_SIZE; ++k) {
  178.                     columns[k][j] += coeffs[k - i - 1] * columns[i][j];
  179.                 }
  180.             }
  181.  
  182.             cnt++;
  183.         }
  184.         else {
  185.             int swaps[2];
  186.             ///   Get swap
  187.             MPI_Bcast(&(swaps[0]), 2, MPI_INT, i % size, MPI_COMM_WORLD);
  188.  
  189.             ///   Perform swap
  190.             for(int j = 0; j < colCnt; ++j) {
  191.                 float tmp = columns[swaps[0]][j];
  192.                 columns[swaps[0]][j] = columns[swaps[1]][j];
  193.                 columns[swaps[1]][j] = tmp;
  194.             }
  195.  
  196.             ///   Get coefficients
  197.             float coeffs[MATRIX_SIZE - i - 1];
  198.             MPI_Recv(&(coeffs[0]), MATRIX_SIZE - i - 1, MPI_FLOAT, i % size,
  199.                      0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
  200.  
  201.  
  202.             ///   Perform subtracting
  203.             for(int j = cnt; j < colCnt; ++j) {
  204.                 for(int k = i + 1; k < MATRIX_SIZE; ++k) {
  205.                     columns[k][j] += coeffs[k - i - 1] * columns[i][j];
  206.                 }
  207.             }
  208.         }
  209.     }
  210.  
  211.     cnt = colCnt - 1;
  212.     if(rank == MATRIX_SIZE % size) {
  213.         cnt--;
  214.     }
  215.  
  216.     ///   Backward pass
  217.     for(int i = MATRIX_SIZE - 1; i >= 0; --i) {
  218.         MPI_Barrier(MPI_COMM_WORLD);
  219.         if(i % size == rank && rank != MATRIX_SIZE % size) {
  220.             float coeffs[i + 1];
  221.             ///   Perform subtracting
  222.             coeffs[i] = columns[i][cnt];
  223.             columns[i][cnt] = 1.;
  224.             for(int j = i - 1; j >= 0; --j) {
  225.                 coeffs[j] = -columns[j][cnt];
  226.                 columns[j][cnt] = 0;
  227.             }
  228.  
  229.             ///   Send coefficients
  230.             MPI_Bsend(&(coeffs[0]), i + 1, MPI_FLOAT, MATRIX_SIZE % size,
  231.                       0, MPI_COMM_WORLD);
  232.  
  233.             cnt--;
  234.         }
  235.         else if(rank == MATRIX_SIZE % size) {
  236.             if(i % size != rank && size != 1) {
  237.                 ///   Get coefficients
  238.                 float coeffs[i + 1];
  239.  
  240.                 MPI_Recv(&(coeffs[0]), i + 1, MPI_FLOAT, i % size,
  241.                          0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
  242.  
  243.                 columns[i][colCnt - 1] /= coeffs[i];
  244.                 for(int j = i - 1; j >= 0; --j) {
  245.                     columns[j][colCnt - 1] += coeffs[j] * columns[i][colCnt - 1];
  246.                 }
  247.             }
  248.             else {
  249.                 columns[i][colCnt - 1] /= columns[i][cnt];
  250.                 for(int j = i - 1; j >= 0; --j) {
  251.                     columns[j][colCnt - 1] -= columns[i][colCnt - 1] * columns[j][cnt];
  252.                     columns[j][cnt] = 0;
  253.                 }
  254.                 cnt--;
  255.             }
  256.         }
  257.     }
  258.  
  259.     MPI_Barrier(MPI_COMM_WORLD);
  260.     if(rank == MATRIX_SIZE % size) {
  261.         for(int i = 0; i < MATRIX_SIZE; ++i) {
  262.             printf("x%d: %.6f\n", i + 1, columns[i][colCnt - 1]);
  263.         }
  264.         fflush(stdout);
  265.     }
  266.  
  267.     free(counts);
  268.     MPI_Barrier(MPI_COMM_WORLD);
  269.  
  270.  
  271.     double endTime = MPI_Wtime();
  272.     if(rank == 0) {
  273.         usleep(500*1000);
  274.         printf("Time: %.6f\n", endTime - startTime);
  275.     }
  276.  
  277.  
  278.     err = MPI_Finalize();
  279.     return 0;
  280. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement