考慮下面的代碼:併發處理從文件
std::vector<int> indices = /* Non overlapping ranges. */;
std::istream& in = /*...*/;
for(std::size_t i= 0; i< indices.size()-1; ++i)
{
in.seekg(indices[i]);
std::vector<int> data(indices[i+1] - indices[i]);
in.read(reinterpret_cast<char*>(data.data()), data.size()*sizeof(int));
process_data(data);
}
我想使這個代碼的並行和儘可能快的可能。
使用PPL將parallizing它的一個方法:
std::vector<int> indices = /* Non overlapping ranges. */;
std::istream& in = /*...*/;
std::vector<concurrency::task<void>> tasks;
for(std::size_t i= 0; i< indices.size()-1; ++i)
{
in.seekg(indices[i]);
std::vector<int> data(indices[i+1] - indices[i]);
in.read(reinterpret_cast<char*>(data.data()), data.size()*sizeof(int));
tasks.emplace_back(std::bind(&process_data, std::move(data)));
}
concurrency::when_all(tasks.begin(), tasks.end()).wait();
這種方法的問題是,我要處理在同一個線程中的數據(配合到CPU高速緩存),因爲它被讀入內存(數據在緩存中很熱),但這並不是這種情況,它只是在浪費使用熱數據的機會。
我有兩個想法如何改善這個,但是,我還沒有能夠實現。
在單獨的任務上開始下一次迭代。
/* ??? */ { in.seekg(indices[i]); std::vector<int> data(indices[i+1] - indices[i]); // data size will fit into CPU cache. in.read(reinterpret_cast<char*>(data.data()), data.size()*sizeof(int)); /* Start a task that begins the next iteration? */ process_data(data); }
使用內存映射文件和映射文件的所需區域和,而不是尋求公正從正確的偏移量指針讀取。使用
parallel_for_each
處理數據範圍。但是,我不明白內存映射文件在讀取內存和緩存時的性能意義。也許我甚至不必考慮緩存,因爲文件只是DMA:d到系統內存,從來沒有通過CPU?
任何建議或意見?
爲什麼不嘗試將文件拆分成更小的文件,然後在單獨的線程中讀取和處理它們?對於文件,您必須考慮CPU綁定和I/O綁定 – askmish 2012-08-16 14:30:43
+1。看起來,如果將內存保存在緩存中,您將獲得的任何好處都將因文件I/O的等待而變得不足。 – 2012-08-17 14:37:15
@BenFulton:假設文件不在OS緩存中,並且/或者我沒有執行此功能的多個併發執行,您是對的。 – ronag 2012-08-17 14:44:35