c++ - 使用 mpi 进行 sobel 边缘检测

标签 c++ opencv parallel-processing mpi

我是一个 mpi 新手。我正在尝试将我的代码与 mpi 并行化(需要更快地运行一些实验)。它应该像这样工作:master 向 slaves 发送一个字符串数组,它们做一些工作并将 status_ready 发送回 master。当所有从站都准备好后,主站进入一个循环并迭代地向从站发送一个 double vector ,从站处理这个 vector 并将它们的结果(2 个 vector )发送回主站。当所有的tje消息都收到后,master会进行处理,循环迭代(master将结果发送给slave等)应该是这样的

#include <iostream>
#include <mpi.h>
#include <cmath>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>

using namespace std;
using namespace cv;
//int mod(int z, int l);

int xGradient(Mat image, int x, int y)
{
  return image.at<uchar>(y-1, x-1) +
    2*image.at<uchar>(y, x-1) +
    image.at<uchar>(y+1, x-1) -
    image.at<uchar>(y-1, x+1) -
    2*image.at<uchar>(y, x+1) -
    image.at<uchar>(y+1, x+1);
}

int yGradient(Mat image, int x, int y)
{
  return image.at<uchar>(y-1, x-1) +
    2*image.at<uchar>(y-1, x) +
    image.at<uchar>(y-1, x+1) -
    image.at<uchar>(y+1, x-1) -
    2*image.at<uchar>(y+1, x) -
    image.at<uchar>(y+1, x+1);
}

int main()
{
  Mat src, grey, dst;
  double start, end;
  int i, gx, gy, sum, argc, awal,akhir, size, rank, slave;
  int master=0;
  char **argv;
  // MPI_Status status;
  awal= MPI_Init(&argc, &argv);
  MPI_Comm_size(MPI_COMM_WORLD, &size);
  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  slave=size-1;
  start=MPI_Wtime();
  if( rank == master )
    {
      // start=MPI_Wtime();
      src= imread("E:/tigaout/Debug/jari.jpg");  
      cvtColor(src,grey,CV_BGR2GRAY);

      //MPI_Send(&(row_pointers[i*share+done][0]), 1, newtype, i, 1, MPI_COMM_WORLD);
      dst = grey.clone();
      if( !grey.data )
        {
          return -1;
        }
      for (i=1; i<slave; i++)
        {
          MPI_Send(&dst, 1, MPI_DOUBLE, i, 1, MPI_COMM_WORLD);
          cout<<"master mengirim data ke rank 1"<<dst<<endl;
        }
    }
  MPI_Barrier(MPI_COMM_WORLD);
  if (rank != master)
    {
      MPI_Recv(&dst, 1, MPI_DOUBLE, 0, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
      cout<<"rank 1 menerima data"<<dst<<endl;
    }
  for(int y = 0; y < grey.rows; y++)
    for(int x = 0; x < grey.cols; x++)
      dst.at<uchar>(y,x) = 0;  

  for(int y = 1; y < grey.rows - 1; y++)
    {
      for(int x = 1; x < grey.cols - 1; x++)
        {
          gx = xGradient(grey, x, y);
          gy = yGradient(grey, x, y);
          sum = abs(gx) + abs(gy);
          sum = sum > 255 ? 255:sum;
          sum = sum < 0 ? 0 : sum;
          dst.at<uchar>(y,x) = sum;


        }
    }


  /*    namedWindow("deteksi tepi sobel");
            imshow("deteksi tepi sobel", dst);

            namedWindow("grayscale");
            imshow("grayscale", grey);

            namedWindow("Original");
            imshow("Original", src);*/

  imwrite( "E:/tigaout/Debug/deteksi jari.jpg", dst );
  MPI_Barrier(MPI_COMM_WORLD);
  end=MPI_Wtime();
  cout<<"waktu eksekusi adalah: "<< end-start << " detik " <<endl;
  akhir=MPI_Finalize();

  //waitKey();

  return 0;
}

我已经尝试使用 mpi 点对点发送/接收来编写此代码。但是我的代码总是出错,我哪里错了,我该如何解决?

最佳答案

通过使用集合,您可能会获得更好的性能和更简单的代码。 slave 向 master 发送数据的第一步相当于 MPI_Gather . master 向每个 slave 发送新数据的步骤是 MPI_Scatter .

我认为到目前为止可能导致您的尝试出现问题的概念部分是 MPI 程序使用 single program, multiple data编程模型。每个等级都在执行相同的代码,但只是获得不同的“等级”值。这似乎在您的 block if (rank == master)if (rank != master) 中可以理解,但是在使用障碍或其他集体操作时,您必须请记住,您传递给它的通信器中的 no ranks 将传递代码中的那个点,直到所有其他点都到达那里。您对 MPI_Send 的调用是阻塞的,因此主等级可能不会通过第一次发送,直到接收等级发布匹配的 MPI_Recv 之后,即永远不会因为接收等级卡在障碍上。

希望对您有所帮助。

关于c++ - 使用 mpi 进行 sobel 边缘检测,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20755632/

相关文章:

algorithm - 如何制作木炭绘图过滤器

python - 将两个图像与 alpha channel 合并

performance - 为什么经典的 asp 脚本或请求为每个客户端顺序运行

c# - Parallel.For 和 Break() 的误解?

c++ - boost regex_match 与 regex_search

c++ - 递归如何获取以前的值?

python - Opencv: AttributeError: 模块 'cv2' 没有属性 'dnn'

c++ - 指向对象类型的指针

c++ - ccache 缓存未命中会减慢编译速度

concurrency - 在 Ada 任务中创建过程或函数