MPI_Scatter问题,无法散布和收集图片矩阵

时间:2019-04-05 22:40:09

标签: c++ opencv parallel-processing mpi

。您好,我的C ++代码有问题。我正在尝试使用OpenCV从我的顺序代码为sobel运算符进行并行实现。

我的实际想法是使用2d缓冲区分散图片,使sobel操作达到averaged_rows * cols。然后进行收集当我发送了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函数发生了什么,我想我可以将单个图片散布到其余的列上以计算sobel,也许我是错的。

如果您要检查我的代码,请在这里。感谢您的宝贵时间。

// > 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;
}

更新:我忘了排名{= 0的rows_av,并且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可以很好地工作,但是我现在正在努力提高内存效率。最后的代码将在上面的pastebin代码中更新。

0 个答案:

没有答案