2012-08-13 81 views
3

考慮下面的代碼:併發處理從文件

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高速緩存),因爲它被讀入內存(數據在緩存中很熱),但這並不是這種情況,它只是在浪費使用熱數據的機會。

我有兩個想法如何改善這個,但是,我還沒有能夠實現。

  1. 在單獨的任務上開始下一次迭代。

    /* ??? */ 
    { 
        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); 
    } 
    
  2. 使用內存映射文件和映射文件的所需區域和,而不是尋求公正從正確的偏移量指針讀取。使用parallel_for_each處理數據範圍。但是,我不明白內存映射文件在讀取內存和緩存時的性能意義。也許我甚至不必考慮緩存,因爲文件只是DMA:d到系統內存,從來沒有通過CPU?

任何建議或意見?

+0

爲什麼不嘗試將文件拆分成更小的文件,然後在單獨的線程中讀取和處理它們?對於文件,您必須考慮CPU綁定和I/O綁定 – askmish 2012-08-16 14:30:43

+0

+1。看起來,如果將內存保存在緩存中,您將獲得的任何好處都將因文件I/O的等待而變得不足。 – 2012-08-17 14:37:15

+0

@BenFulton:假設文件不在OS緩存中,並且/或者我沒有執行此功能的多個併發執行,您是對的。 – ronag 2012-08-17 14:44:35

回答

0

這很可能是你追求錯誤的目標。如前所述,'熱門數據'的任何優勢都將因磁盤速度而變得不足。否則,有些重要的細節你沒有告訴。
1)是否該文件是「大」
2)無論是單記錄是「大」
3)處理是否是「慢」

如果文件是「大」,你最大的任務是確保文件按順序讀取。你的「指數」讓我覺得不然。根據我自己的經驗,最近的例子是6秒比20分鐘,這取決於隨機和順序讀取。沒有開玩笑。

如果這個文件很小,並且你確信它完全被緩存了,你只需要一個同步隊列將任務傳遞給你的線程,那麼在同一個線程中處理就不會有問題。

另一種方式是將「索引」分成兩半,每個線程一個。