2014-02-19 68 views
0

當使用序列化數據執行具有相同標記的多個isend/irecv傳輸時,我看到MPI_ERR_TRUNCATE錯誤boost::mpi。這些是而不是併發傳輸,即不涉及線程。在同一時間只有一個以上的轉帳。這裏有一個簡短的測試程序,展示失敗:boost :: mpi在具有相同標記的多個isend/irecv傳輸中拋出MPI_ERR_TRUNCATE

#include <iostream> 
#include <string> 
#include <vector> 
#include <boost/mpi.hpp> 
#include <boost/serialization/string.hpp> 

static const size_t N = 2; 

int main() { 
    boost::mpi::environment env; 
    boost::mpi::communicator world; 

#if 1 
    // Serialized types fail. 
    typedef std::string DataType; 
#define SEND_VALUE "how now brown cow" 
#else 
    // Native MPI types succeed. 
    typedef int DataType; 
#define SEND_VALUE 42 
#endif 

    DataType out(SEND_VALUE); 
    std::vector<DataType> in(N); 
    std::vector<boost::mpi::request> sends; 
    std::vector<boost::mpi::request> recvs; 
    sends.reserve(N); 
    recvs.reserve(N); 

    std::cout << "Multiple transfers with different tags\n"; 
    sends.clear(); 
    recvs.clear(); 
    for (size_t i = 0; i < N; ++i) { 
     sends.push_back(world.isend(0, i, out)); 
     recvs.push_back(world.irecv(0, i, in[i])); 
    } 
    boost::mpi::wait_all(sends.begin(), sends.end()); 
    boost::mpi::wait_all(recvs.begin(), recvs.end()); 

    std::cout << "Multiple transfers with same tags\n"; 
    sends.clear(); 
    recvs.clear(); 
    for (size_t i = 0; i < N; ++i) { 
     sends.push_back(world.isend(0, 0, out)); 
     recvs.push_back(world.irecv(0, 0, in[i])); 
    } 
    boost::mpi::wait_all(sends.begin(), sends.end()); 
    boost::mpi::wait_all(recvs.begin(), recvs.end()); 

    return 0; 
} 

在這個程序中,我首先在不同的標籤上進行2次傳輸,這可以正常工作。然後,我試圖在相同的標籤2傳輸,該傳輸失敗:

的libC++ abi.dylib:與類型升壓的未捕獲的異常終止:: exception_detail :: clone_impl>:MPI_Unpack:MPI_ERR_TRUNCATE:消息截斷

如果我使用本地MPI數據類型,以便序列化不被調用,事情似乎工作。 MacPorts boost 1.55與OpenMPI 1.7.3同樣出現錯誤,Debian使用OpenMPI 1.4.5提升1.49。我直接用API C接口嘗試了多個帶有相同標籤的傳輸並且似乎可行,但我當然只能傳輸本地MPI數據類型。

我的問題是,在同一個標​​記上是否有多個未完成的傳輸是boost::mpi的有效操作,如果是的話,我的程序中是否存在錯誤或者是否存在boost::mpi

回答

4

在當前版本的增強版中,1.55,boost::mpi不保證不超車消息。此相反,底層MPI API which does

訂單消息是非超車:如果發送者發送兩個消息中 繼承到相同的目的地,以及兩者相匹配相同的接收, 則該操作不能接收該第二消息,如果第一個 仍然未決。如果接收者連續發送兩個接收,並且 都匹配相同的消息,則第二個接收操作不能通過此消息滿足,如果第一個接收操作仍然未決。這個要求促進了發送到接收的匹配。它保證 該消息傳遞代碼是確定性的,如果進程是 單線程和通配符MPI_ANY_SOURCE未使用 接收。

原因boost::mpi不保證非超車是串行化的數據類型在兩個MPI消息,一個用於大小,一個用於有效負載,和irecv爲第二消息無法發佈轉移,直到檢查的第一消息。

正在考慮在boost::mpi中保證不超車的建議。進一步的討論可以在boost::mpi郵件列表here開始。

0

問題可能是您正在等待所有發送完成,然後是所有接收。 MPI希望您的發送和接收能夠及時和數量匹配。我這麼說的意思是,如果您的接聽電話沒有進行,您將無法完成所有的發送電話。

MPI通常處理髮送消息的方式是,當您調用send時,一旦消息被庫處理,它就會從調用中返回。這可能是因爲該消息已被複制到內部緩衝區,或者該消息實際上已傳輸到遠程進程並且已被接收。無論哪種方式,消息必須去某個地方。如果您沒有接收緩衝區已經在等待,則消息必須在內部進行緩衝。最終,實現將耗盡這些緩衝區,並開始做壞事(例如向用戶返回錯誤),您可能會在這裏看到這些錯誤。

解決方案是預先發布您的接收緩衝區。在你的情況下,你可以將isendirecv的所有調用都放到同一個向量中,讓MPI處理所有事情。這將使MPI能夠訪問所有的接收緩衝區,這樣你的消息就可以到達某個地方了。

+0

感謝您的回覆,但事實並非如此。發送和恢復的發佈順序不會改變測試的行爲。而且,如果我只是在等待的時候而不是在發送上,行爲也是一樣的。至於緩衝,請注意我調用了不使用MPI緩衝的'isend()'和'irecv()'(任何緩衝都在'boost :: mpi'中完成)。 – rhashimoto

+0

它不明確使用緩衝,但MPI的實現確實使用緩衝。你有沒有嘗試把發送和接收都放在同一個矢量中? –

+0

單個發送和接收即將開始工作。我的目的不是爲了避免測試程序中的錯誤;它是確定行爲是否正確。還要注意,當直接調用MPI C API時,多個'isend/irecv'傳輸工作,即繞過'boost :: mpi'。 – rhashimoto

相關問題