2016-12-21 29 views
4

大規模なファイルがあり、少数の大きなデータセットが含まれています。各データセットには名前とデータセットサイズ(バイト数)が含まれており、スキップして次のデータセットに移動できます。大きなファイルでスキップするC++ /高速ランダムアクセス

データセット名のインデックスを非常に迅速に作成したいと考えています。ファイルの例は約21MBで、88個のデータセットを含んでいます。 std::ifstreamseekg()を使用して88個の名前をすばやく読み取ると、データセット間をスキップするのに約1300msかかりますが、これを削減したいと考えています。

実際、私は21MBファイル内の所定の位置で約30バイトの88個のチャンクを読んでおり、1300ミリ秒かかります。

これを改善する方法はありますか、それともOSとファイルシステムの制限ですか?私はWindows 7 64bitの下でテストを実行しています。

私は、ファイルの先頭に完全なインデックスを持つ方が良いと思っていますが、ファイル形式にはこれがなく、変更できません。

+0

いくつかのヒントhttp://stackoverflow.com/questions/5166263/how-to-get-iostream-to-perform-b​​etter –

+0

これらのテキストファイルはありますか? Windowsはラインの最後に改行と改行の両方を保存しますか?もしそうなら、ifstreamで論理テキストファイルを検索し、キャリッジリターン文字をフィルタリングしますか?もしそうなら、おそらくあなたは生のバイナリモードでファイルを開くことができます。シークオフセットにCRを含まないようにシーク機能がすべての文字を読み込まないようにしますか?しかし、もちろん、あなたのコードは、フィルタリングされていないキャリッジリターンを無視しなければならないかもしれません。 – WaltK

+0

データフォーマットが変更されていない88個の小さなファイルに分割していますか? – norca

答えて

2

ファイルをスキャンし、キーとインデックスを別々のファイルに入れて独自のヘッダーを作成することができます。ユースケースに応じて、プログラムの開始時とファイルが変更されるたびに1回実行できます。 大きなデータにアクセスする前に、小さいファイルのルックアップが必要なインデックスを提供します。

5

あなたはこれがディスクに戻すことなく、迅速に検索時間のために、アプリケーションの仮想ページにファイルを開きます

(私はboost's implementation.を推奨)、メモリマップされたファイル・インタフェースを使用することができます。

+0

これは、どのようにディスクヘッドを前後に探す必要がないかわかりません。主な違いは、OSがアプリケーションの代わりにシークコマンドを送信していることです。 –

+0

@JeremyFriesnerどちらの場合も、最初のディスクヘッドシークは行われません。主な違いは、ページがカーネルメモリにあり、iostreamによって行われるユーザー空間へのコピーではなく、直接アクセスできることです。 – mascoj

+0

OPが最小限に抑えようとしているのは、カーネルからユーザー空間へのコピー(それほど重要ではない)ではなく、ドライブヘッドの探索です。 mmap()を使用してもシークは回避されず、実際には先読みアルゴリズムの実装がOPのプログラムがmmap()のメモリ領域にアクセスするパターンとどのように相互作用するかに応じてさらに多くを追加する可能性があります) –

0

マルチスレッドでバッファキューイングプロセスを実行できる場合があります。さまざまな量のデータを格納するカスタム構造体を作成できます。

あなたが言った:

各データセットは、それをスキップして次のデータセットに移動することができ、名前とバイト単位のデータセットのサイズが含まれています。

ファイルを何度も開いたり閉じたりするのが遅いため、ファイルを一度に読み込んでフルバッファオブジェクトに格納して解析したり、バッチに格納したりすることができます。これは、ファイルを解析するのが簡単かどうかをテキストまたはバイナリモードで読み込んでいるかどうかによっても変わります。私はファイルからバッファされたサイズのデータ​​量を読み込みながら、複数のバッチを読み込んで後で説明します。

擬似コード

struct Batch { 
    std::string name; // Name of Dataset 
    unsigned size; // Size of Dataset 
    unsigned indexOffset; // Index to next read location 
    bool empty = true;  // Flag to tell if this batch is full or empty 
    std::vector<DataType> dataset; // Container of Data 
}; 

std::vector<Batch> finishedBatches; 

// This doesn't matter on the size of the data set; this is just a buffer size on how much memory to digest in reading the file 
const unsigned bufferSize = "Set to Your Preference" 1MB - 4MB etc. 

void loadDataFromFile(const std::string& filename, unsigned bufferSize, std::vector<Batch>& batches) { 

    // Set ifstream's buffer size 

    // OpenFile For Reading and read in and upto buffer size 

    // Spawn different thread to populate the Batches and while that batch is loading 
    // in data read in that much buffer data again. You will need to have a couple local 
    // stack batches to work with. So if a batch is complete and you reached the next index 
    // location from the file you can fill another batch. 

    // When a single batch is complete push it into the vector to store that batch. 
    // Change its flag and clear its vector and you can then use that empty batch again. 

    // Continue this until you reached end of file.   

} 

これは、ここで2スレッドシステムになります。ファイルを開いたり読み込んだり、ファイルからバッチを埋める作業スレッドを探したり、バッチをコンテナにプッシュしたり、次のバッチを使用するためのスワッピングを行うためのメインスレッド。

関連する問題