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を使用してそれを並列化する 1 つの方法は次のとおりです。

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 キャッシュに収まる) を処理したい (データがキャッシュ内でホットである) ことですが、ここではそうではありません。ホットデータを使用する機会を無駄にしています。

これを改善する方法が2つありますが、どちらも実現できていません。

  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を通過することはないため、キャッシュを考慮する必要さえないのではないでしょうか?

提案やコメントはありますか?

4

1 に答える 1

0

間違った目標を追求している可能性が最も高いです。すでに述べたように、「ホット データ」の利点は、ディスク速度に比べれば小さくなります。そうでなければ、あなたが伝えなかった重要な詳細があります。
1) ファイルが「大きい」
かどうか 2) 単一のレコードが「大きい」
かどうか 3) 処理が「遅い」かどうか

ファイルが「大きい」場合、最大の優先事項は、ファイルが順番に読み取られるようにすることです。あなたの「指標」は私に別のことを考えさせます。私自身の経験からの最近の例は、ランダム読み取りとシーケンシャル読み取りに応じて、6 秒対 20 分です。冗談じゃない。

ファイルが「小さく」、完全にキャッシュされていることが確実な場合は、タスクをスレッドに配信するために同期化されたキューが必要なだけで、同じスレッドで処理することは問題になりません。

もう 1 つの方法は、「インデックス」を各スレッドに 1 つずつ半分に分割することです。

于 2012-08-22T12:27:23.923 に答える