2017-06-06 60 views
0

我試圖通過MPI與不同大小的std::vector<MyClass>進行通信。 MyClass包含可能未初始化或大小不同的矢量的成員。爲此,我寫了一個serialize()deserialize()函數,讀寫這樣的std::vector<MyClass>std::string,然後我通過MPI進行通信。使用MPI將對象的向量序列化爲std :: string

class MyClass { 
    ... 
    int some_int_member; 
    std::vector<float> some_vector_member; 
} 

std::vector<MyClass> deserialize(const std::string &in) { 
    std::istringstream iss(in); 

    size_t total_size; 
    iss.read(reinterpret_cast<char *>(&total_size), sizeof(total_size)); 

    std::vector<MyClass> out_vec; 
    out_vec.resize(total_size); 

    for(MyClass &d: out_vec) { 
     size_t v_size; 
     iss.read(reinterpret_cast<char *>(&d.some_int_member), sizeof(d.some_int_member)); 
     iss.read(reinterpret_cast<char *>(&v_size), sizeof(v_size)); 
     d.some_vector_member.resize(v_size); 
     iss.read(reinterpret_cast<char *>(&d.some_vector_member[0]), v_size * sizeof(float)); 
    } 

    return out_vec; 
} 


std::string serialize(std::vector<MyClass> &data) { 
    std::ostringstream os; 

    size_t total_size = data.size(); 
    os.write(reinterpret_cast<char *>(&total_size), sizeof(total_size)); 

    for(MyClass &d: data) { 
     size_t v_size = d.some_vector_member.size(); 
     os.write(reinterpret_cast<char *>(&some_int_member), sizeof(some_int_member)); 
     os.write(reinterpret_cast<char *>(&v_size), sizeof(v_size)); 
     os.write(reinterpret_cast<char *>(&d.some_vector_member[0]), v_size * sizeof(float)); 
    } 
    return os.str(); 
} 

我工作的實施原則,但有時(並不總是!)MPI在我認爲都與系列化位置進程崩潰。發送的有效載荷可以和MB的胡言亂語一樣大。我懷疑使用std::string作爲容器不是一個好的選擇。使用std::string作爲char[]的容器時是否存在一些限制,我可能會在這裏使用巨大的二進制數據?

(請注意,我不希望使用boost::mpi以其系列化程序一起,我也不希望在一個巨大的圖書館拉如cereal到我的項目)

+0

我不確定你想從答案中得到什麼。這是關於崩潰?然後我們需要一個[mcve]和你目前調試工作的描述。或者這是關於如何正確地進行序列化?或者,這是如何發送複合C++對象與MPI(序列化只是一個答案)?如果這實際上是關於「*通過MPI *實現發送序列化數據」,那麼至少我們需要查看您的MPI代碼。這些問題中的許多問題也很重視意見(「*更好的方法*」),請將重點放在特定目標和標準上。 – Zulan

+0

嗨祖蘭,對不起,這個問題不是很精確。我會嘗試重述它。我在大型數值模擬中使用上述例程,即使許多MPI請求沒有問題,也會有時會崩潰。堆棧跟蹤不是很有幫助(它包含'bad_alloc',所以我猜它是一些內存事物),並且我不能輕鬆創建一個最小工作示例。我懷疑'std :: string'的一些限制是問題,因此我的問題。 – janoliver

+0

你可以嘗試將你的serialize方法封裝在try {...} catch(std :: bad_alloc&){...}塊中。此外,您可以使用內存分析器來分析內存泄漏。 –

回答

1

通常,使用std::string二進制數據雖然有些人可能更喜歡std::vector<char> - 或std::vector<std::byte> C++ 17(see also,請注意C++ 11字符串保證連續的數據)。代碼中有兩個重要的效率問題:

  1. 您總是有三份全部數據。原始對象,序列化的string和中間的[io]stringstream
  2. 您不能預先分配(保留)ostringstream中的數據,這可能會導致過度分配和頻繁的重新分配。

因此,你浪費了大量的內存,這可能有助於bad_alloc。也就是說,它可能非常好,你只是在某處存在內存泄漏。在不知道bad_alloc的原因以及應用程序的性能分析的情況下,無法判斷這是否是實際問題。

相關問題