什么是通过MPI发送OPENCV Mat的最佳方式

时间:2017-04-19 17:21:54

标签: c++ opencv parallel-processing mpi

通过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;
}

1 个答案:

答案 0 :(得分:2)

首先检查原始Mat是否为连续,如果不是,请将其克隆。

然后得到:

  • 信道
原始Mat

并按顺序保存,每个为4个字节,在缓冲区的开头。然后从原始Mat的{​​{1}}指针追加适当数量的字节并发送整批。

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

@Miki提供了一个很好的相关答案here,它展示了上面建议的大多数技术的详细信息 - 具体来看MatMat2str()

我没有做太多的C ++或更多的MPI,我相信任何使用MPI或C ++的人都可以收紧它,但是下面的工作和工作也非常快!

str2Mat()

我放置了一个包含10,000次迭代的循环:

    奴隶中的
  • #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(); }
  • 主人
  • matsnd()

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

所有左对齐的matrcv()语句都只是可以安全删除的调试内容。

注意:

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

关键字:MPI,MPI_Send,MPI_Recv,OpenCV,Mat,image