MPI_Scatter проблема, не могу разбросать и собрать матрицу изображения - PullRequest
0 голосов
/ 06 апреля 2019

. Здравствуйте, у меня проблема с моим кодом C ++. Я пытаюсь сделать параллельную реализацию из моего последовательного кода для оператора sobel, используя OpenCV.

Моя настоящая идея состоит в том, чтобы разбросать изображение с использованием 2d-буфера, сделать операцию sobel для столбцов averaged_rows *. и затем сделать сбор Когда я отправил averaged_rows и каждый ранг получил его, я пытаюсь использовать MPI_Scatter, и появляется эта ошибка выполнения:

sent to 1
sent to 2
sent to 3
recieved by 1
recieved by 2
recieved by 3
[roronoasins-GL552VW:3245] *** An error occurred in MPI_Scatter
[roronoasins-GL552VW:3245] *** reported by process [1759117313,1]
[roronoasins-GL552VW:3245] *** on communicator MPI_COMM_WORLD
[roronoasins-GL552VW:3245] *** MPI_ERR_TRUNCATE: message truncated
[roronoasins-GL552VW:3245] *** MPI_ERRORS_ARE_FATAL (processes in this communicator will now abort,
[roronoasins-GL552VW:3245] ***    and potentially your MPI job)
[roronoasins-GL552VW:03239] 2 more processes have sent help message help-mpi-errors.txt / mpi_errors_are_fatal
[roronoasins-GL552VW:03239] Set MCA parameter "orte_base_help_aggregate" to 0 to see all help / error messages

Что я на самом деле делаю, так это разбрасываю pic буфер, передаю картинку остальным рядам и собравшимся.

MPI_Scatter(pic, cols*rows_av, MPI_INT, picAux, cols*rows_av, MPI_INT, 0, MPI_COMM_WORLD);
  MPI_Bcast (pic3, cols*rows, MPI_INT, 0, MPI_COMM_WORLD);

  int ip_gx, ip_gy, sum;
  for(int y = ip*pic_struct[2]; y < (ip+1)*pic_struct[2] -1; y++){
    for(int x = 1; x < pic_struct[1]- 1; x++){
      int gx = x_gradient(pic3, x, y);
      int gy = y_gradient(pic3, x, y);
      int sum = abs(gx) + abs(gy);
      sum = sum > 255 ? 255:sum;
      sum = sum < 0 ? 0 : sum;
      picAux[y][x] = sum;
    }
  }
  MPI_Gather(picAux, cols*rows_av, MPI_INT, pic, cols*rows_av, MPI_INT, 0, MPI_COMM_WORLD);

Я хотел бы знать, что происходит с функцией Scatter, я подумал, что могу разбросать отдельные кусочки изображения по разным рядам, чтобы вычислить трезвость, возможно, я ошибаюсь.

Мой код здесь, если вы хотите его проверить. Спасибо за ваше время.

// > compile with mpic++ mpi_sobel.cpp  -o mpi_sobel `pkg-config --libs opencv` -fopenmp -lstdc++
#include <iostream>
#include <cmath>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <omp.h>
#include <mpi.h>

using namespace std;
using namespace cv;
Mat src, dst;
/*
  Computes the x component of the gradient vector
  at a given point in a image.
  returns gradient in the x direction

       | 1 0 -1 |
  Gx = | 2 0 -2 |
       | 1 0 -1 |

*/
int x_gradient(int** image, int x, int y)
{
  return image[y-1][x-1] +
          2*image[y][x-1] +
           image[y+1][x-1] -
            image[y-1][x+1] -
             2*image[y][x+1] -
              image[y+1][x+1];
}


/*
  Computes the y component of the gradient vector
  at a given point in a image
  returns gradient in the y direction

       | 1  2  1 |
  Gy = | 0  0  0 |
       |-1 -2 -1 |
*/
int y_gradient(int** image, int x, int y)
{
  return image[y+1][x-1] +
          2*image[y+1][x] +
           image[y+1][x+1] -
            image[y-1][x-1] -
             2*image[y-1][x] -
              image[y-1][x+1];
}

int main(int argc, char** argv)
{
  string picture;
  if (argc == 2) {
    picture = argv[1];
    src = imread(argv[1], CV_LOAD_IMAGE_GRAYSCALE);
  }
  else {
    picture = "input/logan.jpg";
    src = imread(picture.c_str(), CV_LOAD_IMAGE_GRAYSCALE);
  }
  if( !src.data )
  { return -1; }
  dst.create(src.rows, src.cols, src.type());

  int rows_av, rows_extra;
  Size s = src.size();
  int rows = s.height;
  int cols = s.width;
  int pic[rows][cols];int picAux[rows][cols];
  int ** pic3;

  pic3 = new int*[rows];
  for(int y = 0; y < rows; y++)
    pic3[y] = new int[cols];

  int pic_struct[3], pic_struct_recv[3];
  int np, ip;
  double start_time = omp_get_wtime();
  if (MPI_Init(&argc, &argv) != MPI_SUCCESS){
    exit(1);
  }
  MPI_Comm_size(MPI_COMM_WORLD, &np);
  MPI_Comm_rank(MPI_COMM_WORLD, &ip);
  MPI_Status status;

  if(ip==0)
  {
    for(int y = 0; y < rows ; y++)
      for(int x = 0; x < cols; x++)
      {
        pic3[y][x] = src.at<uchar>(y,x);
        pic[y][x] = 0;
        picAux[y][x] = 0;
      }
    src.release();
    rows_av = rows/np;
    //cols_av = cols/np;

    pic_struct[0] = rows;
    pic_struct[1] = cols;
    pic_struct[2] = rows_av;
    //pic_struct[3] = cols_av:
    for(int i=1; i < np; i++)
    {
      //rows = (i <= rows_extra) ? rows_av+1 : rows_av;
      pic_struct[0] = rows;
      MPI_Send(&pic_struct, sizeof(pic_struct), MPI_BYTE, i, 0, MPI_COMM_WORLD);
      cout << "sent to " << i <<  endl;

    }
  }else{//ip
    MPI_Recv(&pic_struct, sizeof(pic_struct), MPI_BYTE, 0, 0, MPI_COMM_WORLD, &status);
    cout << "recieved by " << ip <<  endl;
  }

  MPI_Scatter(pic, cols*rows_av, MPI_INT, picAux, cols*rows_av, MPI_INT, 0, MPI_COMM_WORLD);
  MPI_Bcast (pic3, cols*rows, MPI_INT, 0, MPI_COMM_WORLD);
  cout << "bcast" << endl;
  //MPI_Barrier(MPI_COMM_WORLD);

  int ip_gx, ip_gy, sum;
  for(int y = ip*pic_struct[2]; y < (ip+1)*pic_struct[2] -1; y++){
    for(int x = 1; x < pic_struct[1]- 1; x++){
      ip_gx = x_gradient(src, x, y);
      ip_gy = y_gradient(src, x, y);
      sum = abs(ip_gx) + abs(ip_gy);
      sum = sum > 255 ? 255:sum;
      sum = sum < 0 ? 0 : sum;
      picAux[y][x] = sum;
    }
  }
  MPI_Gather(picAux, cols*rows_av, MPI_INT, pic, cols*rows_av, MPI_INT, 0, MPI_COMM_WORLD);
  cout << "gather" << endl;

  MPI_Finalize();


  if(!ip)
  {
    double time = omp_get_wtime() - start_time;
    for( int i = 0 ; i < rows ; i++ )
    {
      delete [] pic3[i] ;
      delete [] pic3 ;
    }
    cout << "Number of processes: " << np << endl;
    cout << "Rows, Cols: " << rows << " " << cols << endl;
    cout << "Rows, Cols(Division): " << rows_av << ", " << cols << endl << endl;

    cout << "Processing time: " << time << endl;
    for(int i=0; i < 6 ; i++)  picture.erase(picture.begin());
    for(int i=0; i < 4 ; i++)  picture.pop_back();
    picture.insert(0,"output/");
    picture += "-sobel.jpg";
    for(int y = 0; y < rows; y++)
      for(int x = 0; x < cols; x++)
        dst.at<uchar>(y,x) = pic[y][x];

    if(imwrite(picture.c_str(), dst)) cout << "Picture correctly saved as " << picture << endl;
    else  cout << "\nError has occurred being saved." << endl;
  }

  return 0;
}

Обновление : я забыл rows_av в строю! = 0 и pic3 отправка исправлена. Я упаковал src в смежный буфер, и это правильно в каждом ранге.

обновленный код здесь: https://pastebin.com/jPV9mGFW

Я заметил, что в темноте 3/4 есть шум, с этой новой проблемой, я не знаю, является ли сбор сейчас проблемой, или я делаю операции с number_process*rows/total_processes неправильно.

MPI_Scatter(pic, cols*rows_av, MPI_UNSIGNED_CHAR, picAux, cols*rows_av, MPI_UNSIGNED_CHAR, 0, MPI_COMM_WORLD);
  int ip_gx, ip_gy, sum;
  for(int y = ip*rows_av+1; y < (ip+1)*rows_av-1; y++){
    for(int x = 1; x < cols  ; x++){
      ip_gx = x_gradient(src, x, y);
      ip_gy = y_gradient(src, x, y);
      sum = abs(ip_gx) + abs(ip_gy);
      sum = sum > 255 ? 255:sum;
      sum = sum < 0 ? 0 : sum;
      picAux[y][x] = sum;
      //picAux[y*rows_av+x] = sum;
    }
  }
  MPI_Gather(picAux, cols*rows_av, MPI_UNSIGNED_CHAR, pic, cols*rows_av, MPI_UNSIGNED_CHAR, 0, MPI_COMM_WORLD);

Цикл обновлен, и изображение теперь полностью рассчитано, но я не могу использовать изображения размером больше 2048x1536.

for(int y = 1; y < rows_av-1; y++){
    for(int x = 1; x < cols  ; x++){
      ip_gx = x_gradient(src, x, ip*rows_av+y);
      ip_gy = y_gradient(src, x, ip*rows_av+y);
      sum = abs(ip_gx) + abs(ip_gy);
      sum = sum > 255 ? 255:sum;
      sum = sum < 0 ? 0 : sum;
      picAux[y*cols+x] = sum;
    }
  }
  • Как я могу отправить изображения большего размера, чем 2048x1536?
--------------------------------------------------------------------------
mpirun noticed that process rank 2 with PID 0 on node roronoasins-GL552VW exited on signal 11 (Segmentation fault).
--------------------------------------------------------------------------

Размер изображения был ограничен размером стека. с ulimit -s unlimited работает нормально, но сейчас я работаю над повышением эффективности памяти. Последний код будет обновлен в приведенном выше коде.

...