2012-01-05 67 views
1

讀取this後,我仍然想知道發送C/C++結構數據的最佳方式。事實上,我決定使用派生類型,但我遇到了問題。使用MPI派生數據類型

緊接在MPI_Init(...)之後,我有一個函數寫在一個單獨的文件(MPI_NewTypes.cpp/h)中,它基本上用於提交新的數據類型。這裏是一個快照:

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); 

後幾個函數調用在不同的文件中實現的功能,我使用新數據類型:MPI_MSGINSTALLP。但是,我的鏈接器抱怨說它不知道這個新的派生類型是什麼。表面上,這是一個C/C++ scopinq問題,但我沒有把它做對。我如何確保每當我使用新的派生數據類型時,MPI都會知道它存在?每當我在應用程序中使用這種新類型時,我都不想重做所有提交。

我試圖把這個在MPI_NewTypes.h頭文件: MPI_Datatype MPI_MSGINSTALLP

希望MPIC++會看到它,如果我包括它使用新數據類型的文件,在這個頭。

沒有運氣。

任何幫助?

每建議,這裏是啓動MPI頂層文件:

#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的文件中的函數(已示出)。

run(...)函數在另一個文件中,這實際上試圖做MPI-SEND/RECV還定義:

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) 。除函數Add_MPI_Types()的接口聲明外,MPI_MSGINSTALLP.h不包含任何內容。

如果需要更多細節,請讓我知道。

+0

你可以張貼的例子你的實際消息傳遞代碼?它看起來像是一個範圍問題,如果沒有上下文,那麼調試相當困難。 :) – suszterpatt 2012-01-05 14:49:46

回答

4

這絕對是一個範圍問題。 MPI_MSGINSTALLP只是MPI_Datatype類型的普通舊變量,不是您可以在任何地方使用過的特殊文字(基本上是您嘗試使用它的方式)。由於該變量在Add_MPI_Types()內是暫時的,因此在調用run()時間之前它已經不復存在。

就個人而言,我會提出的MPI_MSGINSTALLP的聲明中run(),添加MPI_Datatype&Add_MPI_Types()的參數,並通過MPI_MSGINSTALLP到它,這樣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

這是一個很好的答案,我可以使它工作。但是,問題是關於可行性。我希望能夠進行函數調用並獲取提交的新數據類型,然後在項目中的任何地方重新使用它,而這恰好相當大。我做了一些更多的閱讀,並且,如果我正確地理解了它,每次都使用新的數據類型,它需要提交,然後釋放。所以,如果我在並行線程中執行數十個發送和接收,在不同的文件範圍內,它很快就會變得很難看。 – 2012-01-05 18:12:17

+1

您只需要定義和提交一次數據類型,只要其類型映射仍然正確(即它不代表某些通信之間會發生變化的動態數據結構),您就可以重用它。 'MPI_MSGINSTALLP'看起來像是靜態的,所以你需要做的就是確保它在任何地方都可見。例如,將'MPI_MSGINSTALLP'的定義和'Add_MPI_Types(MPI_MSGINSTALLP)'的調用移動到程序的開頭,並將對MPI_MSGINSTALLP的引用傳遞給任何需要它的函數。或者冒[迅速襲擊]攻擊(http://xkcd.com/292/)並使其成爲全球性的。 :) – suszterpatt 2012-01-05 21:59:18

+0

非常感謝。有空的時候我會再試一次。現在,我繞過了MPI_Pack和MPI_Unpack的混亂。 – 2012-01-25 11:30:27