Advertisement
codegod313

SuperMPICode

May 26th, 2022
543
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #define NUM_OF_THREADS 512
  2. #define IMAGE_NAME "image.jpg"
  3.  
  4.  
  5.  
  6. #include "cuda_runtime.h"
  7. #include "device_launch_parameters.h"
  8. #include <iostream>
  9. #include <iomanip>
  10. #include <stdio.h>
  11. #include <ctime>
  12. #include <chrono>
  13. #include <ctime>
  14. #include <ratio>
  15. #include <opencv4/opencv2/opencv.hpp>
  16. #include <sys/types.h>
  17. #include <dirent.h>
  18. #include <mpi/mpi.h>
  19. #include <vector>
  20.  
  21. struct bgrPixel
  22. {
  23.     uchar blue;
  24.     uchar green;
  25.     uchar red;
  26. };
  27.  
  28. struct processInfo
  29. {
  30.     int number;
  31.     int rows;
  32.     int columns;
  33.     int channels;
  34.     char name[256];
  35. };
  36.  
  37.  
  38.  
  39. __global__ void filterImageOneChannel(uchar *pixels, uchar *output, const int *rows, const int *columns) {
  40.     //printf("%d\n", threadIdx.x);
  41.     int actualPositionInMatrix = blockDim.x * blockIdx.x + threadIdx.x;
  42.     int matrixDimension = *rows * *columns;
  43.     if(actualPositionInMatrix > matrixDimension - 1){
  44.         return;
  45.     }
  46.     int row = actualPositionInMatrix / *columns;
  47.     int column = actualPositionInMatrix % *columns;
  48.     __shared__ uchar firstLine[NUM_OF_THREADS + 2];
  49.     __shared__ uchar secondLine[NUM_OF_THREADS + 2];
  50.     __shared__ uchar thirdLine[NUM_OF_THREADS + 2];
  51.     int upPixelId = actualPositionInMatrix - *columns;
  52.     int downPixelId = actualPositionInMatrix + *columns;
  53.     secondLine[threadIdx.x + 1] = pixels[actualPositionInMatrix];
  54.  
  55.  
  56.     //left side of rectangle generation
  57.     if(threadIdx.x == 0){
  58.         int leftPixelId = actualPositionInMatrix - 1;
  59.         int upLeftPixelId = actualPositionInMatrix - *columns - 1;
  60.         int downLeftPixelId = actualPositionInMatrix + *columns - 1;
  61.         if(column != 0){
  62.             secondLine[threadIdx.x] = pixels[leftPixelId];
  63.         }else{
  64.             secondLine[threadIdx.x] = 0;
  65.         }
  66.         if(row != 0 &&  column !=0){
  67.             firstLine[threadIdx.x] = pixels[upLeftPixelId];
  68.         }else{
  69.             firstLine[threadIdx.x] = 0;
  70.         }
  71.         if(column !=0 && row != *rows - 1){
  72.             thirdLine[threadIdx.x] = pixels[downLeftPixelId];
  73.         }else{
  74.             thirdLine[threadIdx.x] = 0;
  75.         }
  76.     }
  77.  
  78.  
  79.  
  80.     if(upPixelId >= 0){
  81.         firstLine[threadIdx.x + 1] = pixels[upPixelId];
  82.     }else{
  83.         firstLine[threadIdx.x + 1] = 0;
  84.     }
  85.  
  86.     if(downPixelId < matrixDimension){
  87.         thirdLine[threadIdx.x + 1] = pixels[downPixelId];
  88.     }else{
  89.         thirdLine[threadIdx.x + 1] = 0;
  90.     }
  91.  
  92.     //right side of rectangle generation
  93.     if(threadIdx.x == NUM_OF_THREADS-1){
  94.         //printf("i am suka \n");
  95.         int rightPixelId = actualPositionInMatrix + 1;
  96.         int upRightPixelId = actualPositionInMatrix - *columns + 1;
  97.         int downRightPixelId = actualPositionInMatrix + *columns + 1;
  98.         if(column != *columns - 1){
  99.             secondLine[threadIdx.x + 2] = pixels[rightPixelId];
  100.         }else{
  101.             secondLine[threadIdx.x + 2] = 0;
  102.         }
  103.  
  104.         if(row > 0 && column != *columns - 1){
  105.             firstLine[threadIdx.x + 2] = pixels[upRightPixelId];
  106.         }else{
  107.             firstLine[threadIdx.x + 2] = 0;
  108.         }
  109.  
  110.         if(row != *rows - 1 && column != *columns){
  111.             thirdLine[threadIdx.x + 2] = pixels[downRightPixelId];
  112.         }else{
  113.             thirdLine[threadIdx.x + 2] = 0;
  114.         }
  115.     }
  116.     __syncthreads();
  117.     const int filter[3][3]={
  118.     {0, 1, 0},
  119.     {1, 0, -1},
  120.     {0, -1, 0}};
  121.     int result =
  122.      filter[0][0] * firstLine[threadIdx.x] +
  123.      filter[0][1] * firstLine[threadIdx.x + 1] +
  124.      filter[0][2] * firstLine[threadIdx.x + 2] +
  125.      filter[1][0] * secondLine[threadIdx.x] +
  126.      filter[1][1] * secondLine[threadIdx.x + 1] +
  127.      filter[1][2] * secondLine[threadIdx.x + 2] +
  128.      filter[2][0] * thirdLine[threadIdx.x] +
  129.      filter[2][1] * thirdLine[threadIdx.x + 1] +
  130.      filter[2][2] * thirdLine[threadIdx.x + 2];
  131.      if(result > 255){
  132.          result = 255;
  133.      }
  134.      if(result < 0){
  135.          result = 0;
  136.      }
  137.     output[actualPositionInMatrix] = result;
  138. }
  139.  
  140. __global__ void filterImageThreeChannels(bgrPixel *pixels, bgrPixel *output, const int *rows, const int *columns) {
  141.     //printf("%d\n", threadIdx.x);
  142.     int actualPositionInMatrix = blockDim.x * blockIdx.x + threadIdx.x;
  143.     int matrixDimension = *rows * *columns;
  144.     if(actualPositionInMatrix > matrixDimension - 1){
  145.         return;
  146.     }
  147.     int row = actualPositionInMatrix / *columns;
  148.     int column = actualPositionInMatrix % *columns;
  149.     __shared__ bgrPixel firstLine[NUM_OF_THREADS + 2];
  150.     __shared__ bgrPixel secondLine[NUM_OF_THREADS + 2];
  151.     __shared__ bgrPixel thirdLine[NUM_OF_THREADS + 2];
  152.     int upPixelId = actualPositionInMatrix - *columns;
  153.     int downPixelId = actualPositionInMatrix + *columns;
  154.     secondLine[threadIdx.x + 1] = pixels[actualPositionInMatrix];
  155.  
  156.  
  157.     //left side of rectangle generation
  158.     if(threadIdx.x == 0){
  159.         int leftPixelId = actualPositionInMatrix - 1;
  160.         int upLeftPixelId = actualPositionInMatrix - *columns - 1;
  161.         int downLeftPixelId = actualPositionInMatrix + *columns - 1;
  162.         if(column != 0){
  163.             secondLine[threadIdx.x] = pixels[leftPixelId];
  164.         }else{
  165.             secondLine[threadIdx.x].blue = 0;
  166.             secondLine[threadIdx.x].green = 0;
  167.             secondLine[threadIdx.x].red = 0;
  168.         }
  169.         if(row != 0 &&  column !=0){
  170.             firstLine[threadIdx.x] = pixels[upLeftPixelId];
  171.         }else{
  172.             firstLine[threadIdx.x].blue = 0;
  173.             firstLine[threadIdx.x].green = 0;
  174.             firstLine[threadIdx.x].red = 0;
  175.         }
  176.         if(column !=0 && row != *rows - 1){
  177.             thirdLine[threadIdx.x] = pixels[downLeftPixelId];
  178.         }else{
  179.             thirdLine[threadIdx.x].blue = 0;
  180.             thirdLine[threadIdx.x].green = 0;
  181.             thirdLine[threadIdx.x].red = 0;
  182.         }
  183.     }
  184.  
  185.  
  186.  
  187.     if(upPixelId >= 0){
  188.         firstLine[threadIdx.x + 1] = pixels[upPixelId];
  189.     }else{
  190.         firstLine[threadIdx.x + 1].blue = 0;
  191.         firstLine[threadIdx.x + 1].green = 0;
  192.         firstLine[threadIdx.x + 1].red = 0;
  193.     }
  194.  
  195.     if(downPixelId < matrixDimension){
  196.         thirdLine[threadIdx.x + 1] = pixels[downPixelId];
  197.     }else{
  198.         thirdLine[threadIdx.x + 1].blue = 0;
  199.         thirdLine[threadIdx.x + 1].green = 0;
  200.         thirdLine[threadIdx.x + 1].red = 0;
  201.     }
  202.  
  203.     //right side of rectangle generation
  204.     if(threadIdx.x == NUM_OF_THREADS-1){
  205.         //printf("i am suka \n");
  206.         int rightPixelId = actualPositionInMatrix + 1;
  207.         int upRightPixelId = actualPositionInMatrix - *columns + 1;
  208.         int downRightPixelId = actualPositionInMatrix + *columns + 1;
  209.         if(column != *columns - 1){
  210.             secondLine[threadIdx.x + 2] = pixels[rightPixelId];
  211.         }else{
  212.             secondLine[threadIdx.x + 2].blue = 0;
  213.             secondLine[threadIdx.x + 2].green = 0;
  214.             secondLine[threadIdx.x + 2].red = 0;
  215.         }
  216.  
  217.         if(row > 0 && column != *columns - 1){
  218.             firstLine[threadIdx.x + 2] = pixels[upRightPixelId];
  219.         }else{
  220.             firstLine[threadIdx.x + 2].blue = 0;
  221.             firstLine[threadIdx.x + 2].green = 0;
  222.             firstLine[threadIdx.x + 2].red = 0;
  223.         }
  224.  
  225.         if(row != *rows - 1 && column != *columns){
  226.             thirdLine[threadIdx.x + 2] = pixels[downRightPixelId];
  227.         }else{
  228.             thirdLine[threadIdx.x + 2].blue = 0;
  229.             thirdLine[threadIdx.x + 2].green = 0;
  230.             thirdLine[threadIdx.x + 2].red = 0;
  231.         }
  232.     }
  233.     __syncthreads();
  234.     const int filter[3][3]={
  235.     {0, 1, 0},
  236.     {1, 0, -1},
  237.     {0, -1, 0}};
  238.     int resultBlue =
  239.      filter[0][0] * firstLine[threadIdx.x].blue +
  240.      filter[0][1] * firstLine[threadIdx.x + 1].blue +
  241.      filter[0][2] * firstLine[threadIdx.x + 2].blue +
  242.      filter[1][0] * secondLine[threadIdx.x].blue +
  243.      filter[1][1] * secondLine[threadIdx.x + 1].blue +
  244.      filter[1][2] * secondLine[threadIdx.x + 2].blue +
  245.      filter[2][0] * thirdLine[threadIdx.x].blue +
  246.      filter[2][1] * thirdLine[threadIdx.x + 1].blue +
  247.      filter[2][2] * thirdLine[threadIdx.x + 2].blue;
  248.  
  249.     int resultGreen =
  250.      filter[0][0] * firstLine[threadIdx.x].green +
  251.      filter[0][1] * firstLine[threadIdx.x + 1].green +
  252.      filter[0][2] * firstLine[threadIdx.x + 2].green +
  253.      filter[1][0] * secondLine[threadIdx.x].green +
  254.      filter[1][1] * secondLine[threadIdx.x + 1].green +
  255.      filter[1][2] * secondLine[threadIdx.x + 2].green +
  256.      filter[2][0] * thirdLine[threadIdx.x].green +
  257.      filter[2][1] * thirdLine[threadIdx.x + 1].green +
  258.      filter[2][2] * thirdLine[threadIdx.x + 2].green;
  259.  
  260.  
  261.      int resultRed =
  262.      filter[0][0] * firstLine[threadIdx.x].red +
  263.      filter[0][1] * firstLine[threadIdx.x + 1].red +
  264.      filter[0][2] * firstLine[threadIdx.x + 2].red +
  265.      filter[1][0] * secondLine[threadIdx.x].red +
  266.      filter[1][1] * secondLine[threadIdx.x + 1].red +
  267.      filter[1][2] * secondLine[threadIdx.x + 2].red +
  268.      filter[2][0] * thirdLine[threadIdx.x].red +
  269.      filter[2][1] * thirdLine[threadIdx.x + 1].red +
  270.      filter[2][2] * thirdLine[threadIdx.x + 2].red;
  271.  
  272.  
  273.  
  274.      if(resultBlue > 255){
  275.          resultBlue = 255;
  276.      }
  277.      if(resultGreen > 255){
  278.          resultGreen = 255;
  279.      }
  280.      if(resultRed > 255){
  281.          resultRed = 255;
  282.      }
  283.      if(resultBlue < 0){
  284.          resultBlue = 0;
  285.      }
  286.      if(resultGreen < 0){
  287.          resultGreen = 0;
  288.      }
  289.      if(resultRed < 0){
  290.          resultRed = 0;
  291.      }
  292.     output[actualPositionInMatrix].blue = resultBlue;
  293.     output[actualPositionInMatrix].green = resultGreen;
  294.     output[actualPositionInMatrix].red = resultRed;
  295. }
  296.  
  297.  
  298. __host__ bgrPixel *imageToPixelsBGR(cv::Mat image){
  299.     bgrPixel *pixels = (bgrPixel *)malloc(sizeof(bgrPixel) * image.cols * image.rows);
  300.     for (int i = 0; i < image.rows; i++){
  301.         for(int j = 0; j < image.cols; j++){
  302.             pixels[i * image.cols + j].blue = image.at<cv::Vec3b>(i, j)[0];
  303.             pixels[i * image.cols + j].green = image.at<cv::Vec3b>(i, j)[1];
  304.             pixels[i * image.cols + j].red = image.at<cv::Vec3b>(i, j)[2];
  305.         }
  306.     }
  307.     return pixels;
  308. }
  309.  
  310. __host__ bgrPixel *dataToBGRPixels(uchar *data, int rows, int cols){
  311.     bgrPixel *pixels = (bgrPixel *)malloc(sizeof(bgrPixel) * cols * rows);
  312.     for(int i = 0; i<rows * cols; i++){
  313.         pixels[i].blue = data[i * 3];
  314.         pixels[i].green = data[i * 3 + 1];
  315.         pixels[i].red = data[i * 3 + 2];
  316.     }
  317.     return pixels;
  318. }
  319.  
  320. __host__ uchar *BGRPixelsToRawData(bgrPixel *pixels, int n){
  321.     uchar *data = (uchar *)malloc(sizeof(uchar) * n * 3);
  322.     for(int i = 0; i<n; i++){
  323.         data[i * 3] = pixels[i].blue;
  324.         data[i * 3 + 1] = pixels[i].green;
  325.         data[i * 3 + 1] = pixels[i].red;
  326.     }
  327.     return data;
  328. }
  329.  
  330.  
  331.  
  332. int main()
  333. {
  334.     MPI_Init(NULL, NULL);
  335.     int rank;
  336.     MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  337.     int namelen;
  338.     char processorName[MPI_MAX_PROCESSOR_NAME];
  339.     MPI_Get_processor_name(processorName, &namelen);
  340.     if(rank == 0){
  341.         std::cout << "My rank is " << rank << " and i am master. I am running on " << processorName << std::endl;
  342.         DIR *dir;
  343.         struct dirent *entry;
  344.  
  345.         dir = opendir("./images");
  346.         if (!dir) {
  347.             perror("diropen");
  348.             exit(1);
  349.         }
  350.         int quantutyOfProcesses;
  351.         MPI_Comm_size(MPI_COMM_WORLD, &quantutyOfProcesses);
  352.         if(quantutyOfProcesses == 1){
  353.             exit(1);
  354.         }
  355.         std::vector<processInfo> info;
  356.         int currentProcessNumber = 1;
  357.        
  358.         while ( (entry = readdir(dir)) != NULL) {
  359.             if(entry->d_name[0] == '.'){
  360.                 continue;
  361.             }
  362.             processInfo current;
  363.             strcpy(current.name, entry->d_name);
  364.             char path[256] = "images/";
  365.             strcat(path, current.name);
  366.             cv::Mat image = cv::imread(path);
  367.             current.columns = image.cols;
  368.             current.rows = image.rows;
  369.             current.number = currentProcessNumber;
  370.             current.channels = image.channels();
  371.             //current.channels = 1;
  372.             info.push_back(current);
  373.             char command = 'r';
  374.             MPI_Send(&command, 1, MPI_CHAR, currentProcessNumber, 0, MPI_COMM_WORLD);
  375.             MPI_Send(&(current.channels), 1, MPI_INT, currentProcessNumber, 0, MPI_COMM_WORLD);
  376.             MPI_Send(&image.rows, 1, MPI_INT, currentProcessNumber, 0, MPI_COMM_WORLD);
  377.             MPI_Send(&image.cols, 1, MPI_INT, currentProcessNumber, 0, MPI_COMM_WORLD);
  378.             MPI_Send(image.data, image.rows * image.cols * current.channels, MPI_UNSIGNED_CHAR, currentProcessNumber, 0, MPI_COMM_WORLD);
  379.             currentProcessNumber++;
  380.             if(currentProcessNumber == quantutyOfProcesses){
  381.                 currentProcessNumber = 1;
  382.             }
  383.         }
  384.  
  385.         closedir(dir);
  386.         for(int i = 0; i<info.size(); i++){
  387.             uchar *data = (uchar *)malloc(sizeof(uchar) * info[i].columns * info[i].rows * info[i].channels);
  388.             MPI_Recv(data, info[i].columns * info[i].rows * info[i].channels, MPI_UNSIGNED_CHAR, info[i].number, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
  389.             char path[256] = "images/";
  390.             strcat(path, info[i].name);
  391.             cv::Mat image = cv::imread(path);
  392.             image.data = data;
  393.             char savePath[256] = "filteredImages/filtered";
  394.             strcat(savePath, info[i].name);
  395.             cv::imwrite(savePath, image);
  396.         }
  397.         for(int i = 1; i<quantutyOfProcesses; i++){
  398.             char command = 'e';
  399.             MPI_Send(&command, 1, MPI_CHAR, i, 0, MPI_COMM_WORLD);
  400.         }
  401.     }else{
  402.         while (true)
  403.         {
  404.             char command;
  405.             MPI_Recv(&command, 1, MPI_CHAR, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
  406.             if(command == 'e'){
  407.                 break;
  408.             }
  409.             int channels, rows, columns;
  410.             MPI_Recv(&channels, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
  411.             MPI_Recv(&rows, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
  412.             MPI_Recv(&columns, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
  413.             if(channels == 1){
  414.                 uchar *data = (uchar *)malloc(sizeof(uchar) * columns * rows);
  415.                 MPI_Recv(data, rows * columns, MPI_UNSIGNED_CHAR, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
  416.                 std::cout << "Image received on " << processorName << std::endl;
  417.                 dim3 threads(NUM_OF_THREADS);
  418.                 int blocksNum = rows * columns / NUM_OF_THREADS;
  419.                 if(rows * columns % NUM_OF_THREADS){
  420.                     blocksNum++;
  421.                 }
  422.                 dim3 blocks(blocksNum);
  423.                 uchar *deviceData, *deviceOutput;
  424.                 int *rowsDevice;
  425.                 int *columnsDevice;
  426.                 cudaMalloc(&deviceData, sizeof(uchar) * rows * columns);
  427.                 cudaMalloc(&deviceOutput, sizeof(uchar) * rows * columns);
  428.                 cudaMalloc(&rowsDevice, sizeof(int));
  429.                 cudaMalloc(&columnsDevice, sizeof(int));
  430.                
  431.                 cudaMemcpy(deviceData, data, rows * columns * sizeof(uchar), cudaMemcpyHostToDevice);
  432.                 cudaMemcpy(rowsDevice, &rows, sizeof(int),cudaMemcpyHostToDevice);
  433.                 cudaMemcpy(columnsDevice, &columns, sizeof(int),cudaMemcpyHostToDevice);
  434.  
  435.                 cudaEvent_t start, stop;
  436.                 cudaEventCreate(&start);
  437.                 cudaEventCreate(&stop);
  438.  
  439.                 cudaEventRecord(start, 0);
  440.                 filterImageOneChannel<<<blocks, threads>>>(deviceData, deviceOutput, rowsDevice, columnsDevice);
  441.                 cudaEventRecord(stop, 0);
  442.                
  443.                 cudaEventSynchronize(stop);
  444.  
  445.                 float elapsedTime;
  446.  
  447.                 cudaEventElapsedTime(&elapsedTime, start, stop);
  448.  
  449.  
  450.                 printf("time - %f", elapsedTime * 0.0001);
  451.  
  452.                 cudaEventDestroy(start);
  453.                 cudaEventDestroy(stop);
  454.                 uchar* filteredData = (uchar *)malloc(sizeof(uchar) * rows * columns);
  455.                 cudaMemcpy(filteredData, deviceOutput, sizeof(uchar) * rows * columns, cudaMemcpyDeviceToHost);
  456.                 MPI_Send(filteredData, rows * columns, MPI_UNSIGNED_CHAR, 0, 0, MPI_COMM_WORLD);
  457.             }else{
  458.                 uchar *data = (uchar *)malloc(sizeof(uchar) * columns * rows * channels);
  459.                 MPI_Recv(data, rows * columns * channels, MPI_UNSIGNED_CHAR, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
  460.                 std::cout << "Image received on " << processorName << std::endl;
  461.                 dim3 threads(NUM_OF_THREADS);
  462.                 int blocksNum = rows * columns / NUM_OF_THREADS;
  463.                 if(rows * columns % NUM_OF_THREADS){
  464.                     blocksNum++;
  465.                 }
  466.                 dim3 blocks(blocksNum);
  467.                 bgrPixel *deviceData, *deviceOutput;
  468.                 int *rowsDevice;
  469.                 int *columnsDevice;
  470.                 cudaMalloc(&deviceData, sizeof(bgrPixel) * rows * columns);
  471.                 cudaMalloc(&deviceOutput, sizeof(bgrPixel) * rows * columns);
  472.                 cudaMalloc(&rowsDevice, sizeof(int));
  473.                 cudaMalloc(&columnsDevice, sizeof(int));
  474.  
  475.                 bgrPixel *dataBGR = dataToBGRPixels(data, rows, columns);
  476.                
  477.                 cudaMemcpy(deviceData, dataBGR, rows * columns * sizeof(bgrPixel), cudaMemcpyHostToDevice);
  478.                 cudaMemcpy(rowsDevice, &rows, sizeof(int),cudaMemcpyHostToDevice);
  479.                 cudaMemcpy(columnsDevice, &columns, sizeof(int),cudaMemcpyHostToDevice);
  480.  
  481.                 cudaEvent_t start, stop;
  482.                 cudaEventCreate(&start);
  483.                 cudaEventCreate(&stop);
  484.  
  485.                 cudaEventRecord(start, 0);
  486.                 filterImageThreeChannels<<<blocks, threads>>>(deviceData, deviceOutput, rowsDevice, columnsDevice);
  487.                 cudaEventRecord(stop, 0);
  488.                
  489.                 cudaEventSynchronize(stop);
  490.  
  491.                 float elapsedTime;
  492.  
  493.                 cudaEventElapsedTime(&elapsedTime, start, stop);
  494.  
  495.  
  496.                 printf("time - %f", elapsedTime * 0.0001);
  497.  
  498.                 cudaEventDestroy(start);
  499.                 cudaEventDestroy(stop);
  500.                 bgrPixel* filteredDataBGR = (bgrPixel *)malloc(sizeof(bgrPixel) * rows * columns);
  501.                 cudaMemcpy(filteredDataBGR, deviceOutput, sizeof(bgrPixel) * rows * columns, cudaMemcpyDeviceToHost);
  502.                 uchar* filteredData = BGRPixelsToRawData(filteredDataBGR, rows * columns);
  503.                 MPI_Send(filteredData, rows * columns * channels, MPI_UNSIGNED_CHAR, 0, 0, MPI_COMM_WORLD);
  504.             }
  505.         }
  506.     }
  507.        
  508.     MPI_Barrier(MPI_COMM_WORLD);
  509.     return 0;
  510. }
  511.  
  512.  
Advertisement
RAW Paste Data Copied
Advertisement