2012-01-05 10 views
1

thisを読んだ後でも、C/C++構造体データを送信する最良の方法が不思議です。実際、派生型を使用することに決めましたが、問題にぶつかっています。MPIの派生データ型を使用する

MPI_Init(...)の直後には、基本的に新しいデータ型をコミットするために使用される別のファイル(MPI_NewTypes.cpp/h)で書かれた関数があります。ここでは、スナップショットがある:MPI_MSGINSTALLP:機能のカップルの後

int loop_counter; 
    msgInstallP InstallPStruct; 
    MPI_Datatype MPI_MSGINSTALLP; 
    MPI_Datatype type[4] = {MPI_INT, MPI_INT, MPI_INT, MPI_CHAR}; 
    int blocklen[4] = { 
         sizeof(InstallPStruct.type), 
         sizeof(InstallPStruct.location), 
         sizeof(InstallPStruct.processID), 
         sizeof(InstallPStruct.name) 
         }; 

    MPI_Aint  disp[4]; 
    int   base; 
    MPI_Address(&InstallPStruct,    disp); 
    MPI_Address(&InstallPStruct.location,  disp+1); 
    MPI_Address(&InstallPStruct.processID,  disp+2); 
    MPI_Address(&InstallPStruct.name,   disp+3); 
    base = disp[0]; 

    for (loop_counter=0; loop_counter < 4; loop_counter++) 
     { 
     disp[loop_counter] = disp[loop_counter] - base; 
     } 

    MPI_Type_struct(
        4, /*count of elements */ 
        blocklen, /* array_of_blocklengths */ 
        disp, /* array_of_displacements */ 
        type, /* array_of_types */ 
        &MPI_MSGINSTALLP /* newtype */ 
        ); 

    MPI_Type_commit(&MPI_MSGINSTALLP); 

は、私は新しいデータ型を使用しています、別のファイルに実装された関数の呼び出し。しかし、私のリンカーは、この新しい派生型が何であるかを知らないと不平を言っています。外見上は、これはC/C++ scopinqの質問ですが、私はそれを正しく理解していません。新しい派生データ型を使用するたびに、MPIはそれが存在することを知るでしょうか?この新しいタイプをアプリケーションで使用するたびに、すべてのコミットをやり直したくないです。

私はMPI_NewTypes.hヘッダーファイルでこれを入れてみました: MPI_Datatype MPI_MSGINSTALLP

を私は新しいデータ型を使用してファイルにこのヘッダーが含まれている場合MPICは++、それを見るだろうと期待して。

No luck。

助けが必要ですか?ここで

#include <atomic> 
#include "mpi.h" 
#include <iostream> 
#include "Fifo.h" 
#include <thread> 
#include <fstream> 
#include <unistd.h> 
#include <mpi.h> 
#include "GlobalSettings.h" 
#include "Run.h" 
#include "Add_MPI_Types.h" 

int main(int argc, char **argv) 
{ 
    int myrank; 
    int desired_thread_support = MPI_THREAD_MULTIPLE; 
    int provided_thread_support; 

    MPI_Init_thread(&argc, &argv, desired_thread_support, &provided_thread_support); 

    /* check if the thread support has been provided */ 
    if (provided_thread_support!=desired_thread_support) 
    { 
     std::cout << "MPI thread support not available! Aborted. " << std::endl; 
    } 

    MPI_Comm_set_errhandler(MPI_COMM_WORLD, MPI_ERRORS_RETURN); 

    Add_MPI_Types(); 

    /* get rank information */ 
    MPI_Comm_rank(MPI_COMM_WORLD, &myrank); 

    /* Rank 0 is always the master, other ranks are slaves */ 
    if (MASTERNODE == myrank) 
    { 
     /* run the wrapper for master node */ 
     run(MASTERAPPLICATION); 
    } 
    else 
    { 
     /* run the wrapper for the slave node */ 
     run(SLAVEAPPLICATION); 
    } 
    MPI_Finalize(); 
    return 0; 
} 

Add_MPI_Types();はMPI_NewTypes.cpp/hのファイルに存在する、新しいデータ型をコミットする機能です(すでに示した:ここ

提案パー

は、MPIを開始し、トップレベルのファイルがあります)。

run(...)機能は、実際にMPI-送信/レシーバを実行しようとする他のファイルで定義されている:

msgInstallP InstallPMessage; 
    InstallPMessage = *(msgInstallP*)Data; 
    //Add_MPI_msgInstallP_Type(); 
    MPI_Ssend(
      (void*)&InstallPMessage,    /* Payload */ 
      sizeof(msgInstallP),     /* size of the payload */ 
      MPI_MSGINSTALLP,      /* MPI Data type */ 
      InstallPMessage.location,    /* location to which the message is being sent */ 
      InstallPMessage.type,     /* Tag */ 
      MPI_COMM_WORLD      /* Communicator */ 
      ); 

msgInstallPは、C/C++構造体型である(およびMPIにおけるその等価物MPI_MSGINSTALLPあります) 。 MPI_MSGINSTALLP.hには、関数Add_MPI_Types()のインタフェース宣言以外のものは含まれていません。

詳細が必要な場合は教えてください。

+0

個人的に、私は、run()MPI_MSGINSTALLPの宣言を移動Add_MPI_Types()のパラメータにMPI_Datatype&を追加し、run()は次のように見えるように、それにMPI_MSGINSTALLPを渡しますあなたの実際のメッセージはコードを渡しますか?スコープの問題のように見えますが、コンテキストなしでデバッグするのはかなり困難です。 :) – suszterpatt

答えて

4

これは間違いなくスコープの問題です。 MPI_MSGINSTALLPは、タイプMPI_Datatypeの単なる古い変数です。一度コミットした場所で使用できる特別なリテラルではありません(これは、基本的には使用しようとしている方法です)。変数はAdd_MPI_Types()の中に一時的に存在するため、run()が呼び出されるまでにはその変数は存在しなくなりました。あなたがの例を投稿することができます

msgInstallP InstallPMessage; 
InstallPMessage = *(msgInstallP*)Data; 
MPI_Datatype MPI_MSGINSTALLP; 
Add_MPI_Types(MPI_MSGINSTALLP); 
//Add_MPI_msgInstallP_Type(); 
MPI_Ssend(
      (void*)&InstallPMessage,    /* Payload */ 
      sizeof(msgInstallP),     /* size of the payload */ 
      MPI_MSGINSTALLP,      /* MPI Data type */ 
      InstallPMessage.location,    /* location to which the message is being sent */ 
      InstallPMessage.type,     /* Tag */ 
      MPI_COMM_WORLD      /* Communicator */ 
      ); 
+0

これは良い答えです、私はそれを動作させることができます。しかし、問題は実現可能性についてです。私は関数呼び出しを行い、コミットした新しいデータ型を取得してから、プロジェクト内のどこにでも再利用できることを期待していました。私はもう少し読んだことがあります。正しく理解すれば、毎回新しいデータ型が使用され、コミットされ、次に割り当てが解除される必要があります。だから、もし私がたくさんの送受信をしていて、異なるファイルスコープで並列スレッドで受信すると、それはすぐに醜くなるでしょう。 –

+1

データ型を一度定義してコミットするだけで、タイプマップが正しい場合(つまり、通信間で変化する動的データ構造を表すものではない場合)、再利用することができます。 'MPI_MSGINSTALLP'は静的なもののように見えるので、どこからでも見えるようにするだけです。たとえば、 'MPI_MSGINSTALLP'の定義と' Add_MPI_Types(MPI_MSGINSTALLP) 'の呼び出しをプログラムの先頭に移動し、' MPI_MSGINSTALLP'への参照を必要な関数に渡します。あるいは、[velociraptor attack](http://xkcd.com/292/)の危険にさらされ、それをグローバルにする。 :) – suszterpatt

+0

ありがとう。私は時間があるときにこれをもう一度試してみるつもりです。今のところ、私はMPI_PackとMPI_Unpackで混乱を回避しました。 –

関連する問題