2017-04-19 19 views
2

OPENCV MatをMPIに送信する最適な方法は何ですか?今私はMatint**に賭けることによってそれをしましたが、これは少し遅い解決です。OPENCVをMPI経由で送信する最適な方法

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

あなたがあることを考えるのint ** 'だけでなく、特定の測定結果'への変換に使用したコードをご提示ください*スロー*? – Zulan

+0

コードを投稿しました – RicUfa

+0

MPIまたはパフォーマンス測定結果が表示されません。 – Zulan

答えて

2

オリジナルを確認してくださいMatが最初に連続していない場合はクローンしてください。

  • 列原Mat
  • タイプ
  • チャネル

とで、そのために4つのバイトとしてそれぞれ保存します。

それからちょうど得ますバッファの先頭その後、元のMatdataポインタから適切なバイト数を追加し、全体を送信します。

受信側の反対側を行います...バッファから最初の4つの整数を読み取り、対応するサイズのMatを作成し、残りのデータをその中にロードします。


@Mikiは、上記の提案技術のほとんどの詳細を示している優れた、関連答えhereを提供 - 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(); 
} 

は、私は約1万回の繰り返しでループを置く:スレーブで

  • matsnd()、およびマスター

  • matrcv()、それが万回の反復のために1.9秒かかりました。あなたはタイミングを見せなかったので、私は比較できません。

    左揃えのすべてのcout文は、安全に削除できるデバッグ用のものです。

    注:Iを使用し、上記のテストをしている一方で

    、私がので、私は、送信バイト数の計算は、(おそらく、アライメント制約が存在する場合)は、いくつかの状況で正しくないことを学びました。ご興味のある方は、this answerをご確認ください。

    キーワード:MPI、MPI_Send関数、MPI_RECV、OpenCVの、マット、画像

  • +0

    @Mikiの先日、私は関連する回答を見たことがありますが瞬間にそれを見つけるとそれは遅れているので、私は明日また捜索し、できるならリンクを追加します。 –

    +1

    行列が大きい場合は、MPI構造体のデータ型をいくつかの要素に登録し、すべての要素を単一の配列にまとめる必要なしに、記述子とデータの両方を直接送信する方が安いでしょう。受信側では、 'MPI_Probe'と' MPI_Get_count'を使ってデータのサイズを決定し、行列をあらかじめ割り当てることができます。 –

    +1

    ここに私が似たような質問のために書いたコードがあります。http://stackoverflow.com/questions/28782951/segmentation-fault-while-using-mpi-and-opencv-together/28794709#28794709サイズとバッファの送信'im.data'によって指摘されています。 – francis

    関連する問題