通过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个字节。然后,从原始Mat
的data
指针附加适当的字节并发送全部。
在接收端进行相反的操作...从缓冲区读取前四个整数,并创建相应大小的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