什么是通过MPI发送OpenCV垫的最佳方法



通过MPI发送OPENCV Mat的最佳方法是什么?现在,我通过将Mat转到int**来做到这一点,但这有点慢。

A = alloc2d(n , m);
for (int i = 0; i < n ; ++i)
    for (int j = 0; j < m ; ++j)
        A[i][j] = img.at<uchar>(i , j);
/////////////////////////////////////
int ** alloc2d(int rows, int cols) {
    int * data = (int *)malloc(rows * cols * sizeof(int));
    int ** arr = (int **)malloc(rows * sizeof(int *));
    for (int i = 0; i < rows; ++i)
        arr[i] = &(data[cols * i]);
    return arr;
}

检查原始 Mat是连续的,如果不是,则克隆。

然后得到:

  • 类型
  • 频道
原始Mat

在缓冲区开始时按该顺序保存为4个字节。然后,从原始Matdata指针附加适当的字节并发送全部。

在接收端进行相反的操作...从缓冲区读取前四个整数,并创建相应大小的Mat,然后将其余数据加载到其中。


@miki在这里提供了一个非常相关的答案,该答案演示了上面建议的大多数技术的细节 - 专门查看Mat2str()str2Mat()

我没有做太多C 或太多MPI,我相信任何使用MPI或C 的人都可以将其收紧,但是以下工作也很快工作!

#include <cstdlib>
#include <iostream>
#include <iomanip>
#include <ctime>
#include <iostream>
#include <string>
#include <chrono>
#include <thread>
#include <opencv2/opencv.hpp>
#include "opencv2/highgui/highgui.hpp"
#include "mpi.h"
using namespace std;
using namespace cv;
const int MAXBYTES=8*1024*1024;
uchar buffer[MAXBYTES];
void matsnd(const Mat& m,int dest){
      int rows  = m.rows;
      int cols  = m.cols;
      int type  = m.type();
      int channels = m.channels();
      memcpy(&buffer[0 * sizeof(int)],(uchar*)&rows,sizeof(int));
      memcpy(&buffer[1 * sizeof(int)],(uchar*)&cols,sizeof(int));
      memcpy(&buffer[2 * sizeof(int)],(uchar*)&type,sizeof(int));
      // See note at end of answer about "bytes" variable below!!!
      int bytespersample=1; // change if using shorts or floats
      int bytes=m.rows*m.cols*channels*bytespersample;
cout << "matsnd: rows=" << rows << endl;
cout << "matsnd: cols=" << cols << endl;
cout << "matsnd: type=" << type << endl;
cout << "matsnd: channels=" << channels << endl;
cout << "matsnd: bytes=" << bytes << endl;
      if(!m.isContinuous())
      { 
         m = m.clone();
      }
      memcpy(&buffer[3*sizeof(int)],m.data,bytes);
      MPI_Send(&buffer,bytes+3*sizeof(int),MPI_UNSIGNED_CHAR,dest,0,MPI_COMM_WORLD);
}
Mat matrcv(int src){
      MPI_Status status;
      int count,rows,cols,type,channels;
      MPI_Recv(&buffer,sizeof(buffer),MPI_UNSIGNED_CHAR,src,0,MPI_COMM_WORLD,&status);
      MPI_Get_count(&status,MPI_UNSIGNED_CHAR,&count);
      memcpy((uchar*)&rows,&buffer[0 * sizeof(int)], sizeof(int));
      memcpy((uchar*)&cols,&buffer[1 * sizeof(int)], sizeof(int));
      memcpy((uchar*)&type,&buffer[2 * sizeof(int)], sizeof(int));
cout << "matrcv: Count=" << count << endl;
cout << "matrcv: rows=" << rows << endl;
cout << "matrcv: cols=" << cols << endl;
cout << "matrcv: type=" << type << endl;
      // Make the mat
      Mat received= Mat(rows,cols,type,(uchar*)&buffer[3*sizeof(int)]);
      return received;
}
int main ( int argc, char *argv[] )
{
   // Initialise MPI
   MPI::Init (argc,argv);
   //  Get our rank
   int id = MPI::COMM_WORLD.Get_rank();
   if(id==0) 
   {
      // MASTER - wait to receive image from slave and write to disk for checking
      Mat received=matrcv(1);
      imwrite("received.jpg",received);
   }else{
      // Slave - read Mat from disk and send to master
      Mat image=imread("image.jpg",IMREAD_COLOR);
      matsnd(image,0);
   }
   //  Terminate MPI
   MPI::Finalize();
}

我在围绕10,000次迭代的循环:

  • matsnd()在从属中,
  • Master中的matrcv()

,10,000次迭代花了1.9秒。我无法比较,因为您没有显示任何时间。

所有的 cout语句硬左右是可以安全删除的调试内容。

注意:

虽然我已经使用并测试了上述内容,但此后,我了解到,在某些情况下,我发送的字节数的计算可能是不正确的(可能存在对齐约束的地方(。如果您有兴趣,请检查此答案。

关键字:mpi,mpi_send,mpi_recv,opencv,opencv,mat,image

最新更新