通过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;
}
答案 0 :(得分:2)
首先检查原始Mat
是否为连续,如果不是,请将其克隆。
然后得到:
Mat
的并按顺序保存,每个为4个字节,在缓冲区的开头。然后从原始Mat
的{{1}}指针追加适当数量的字节并发送整批。
在接收端执行相反的操作...从缓冲区中读取前四个整数并创建相应大小的data
并将剩余的数据加载到其中。
@Miki提供了一个很好的相关答案here,它展示了上面建议的大多数技术的详细信息 - 具体来看Mat
和Mat2str()
。
我没有做太多的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