簡體   English   中英

使用OpenMP並行化輸出

[英]Parallelize output using OpenMP

我編寫了一個必須處理大量數據的C ++應用程序。 使用OpenMP我很好地並行化了處理階段,並且令人尷尬地發現輸出寫入現在是瓶頸。 我決定在那里使用parallel for ,因為我輸出項目的順序是無關緊要的; 它們只需要輸出為連貫的塊。

下面是輸出代碼的簡化版本,顯示除“兩個自定義迭代器”中的兩個自定義迭代器之外的所有變量。 我的問題是:這是解決這個問題的正確和最佳方法嗎? 我讀到了關於barrier ,我需要它嗎?

long i, n = nrows();

#pragma omp parallel for
for (i=0; i<n; i++) {
    std::vector<MyData> related;
    for (size_t j=0; j < data[i].size(); j++)
        related.push_back(data[i][j]);
    sort(related.rbegin(), related.rend());

    #pragma omp critical
    {
        std::cout << data[i].label << "\n";
        for (size_t j=0; j<related.size(); j++)
            std::cout << "    " << related[j].label << "\n";
    }
}

(我將這個問題標記為c因為我認為OpenMP在C和C ++中非常相似。如果我錯了,請糾正我。)

解決輸出爭用的一種方法是將線程局部輸出寫入字符串流(可以並行完成),然后將內容推送到cout (需要同步)。

像這樣的東西:

#pragma omp parallel for
for (i=0; i<n; i++) {
    std::vector<MyData> related;
    for (size_t j=0; j < data[i].size(); j++)
        related.push_back(data[i][j]);
    sort(related.rbegin(), related.rend());

    std::stringstream buf;
    buf << data[i].label << "\n";
    for (size_t j=0; j<related.size(); j++)
        buf << "    " << related[j].label << "\n";

    #pragma omp critical
    std::cout << buf.rdbuf();
}

這提供了更細粒度的鎖定,並且性能應該相應地增加。 另一方面,這仍然使用鎖定。 另一種方法是使用一個流緩沖區數組,每個線程一個,並在並行循環按順序將它們推送到cout 這具有避免昂貴鎖定的優點,並且無論如何必須序列化cout的輸出。

另一方面,您甚至可以嘗試省略上述代碼中的critical部分。 根據我的經驗,這是有效的,因為底層流有自己的控制並發的方式。 但我相信這種行為是嚴格的實現定義而不是可移植的。

cout爭論仍然是一個問題。 為什么不在一些線程本地存儲中輸出結果並將它們集中整理到所需位置,這意味着沒有爭用。 例如,您可以讓並行代碼的每個目標線程寫入單獨的文件流或內存流,然后將它們連接起來,因為排序並不重要。 或者從多個地方而不是一個地方對結果進行后處理 - 沒有爭用,只需要單次寫入。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM