4

重複の可能性:
C++ でのバイナリ ファイルの書き込みが非常に高速

メモリ内に多数の符号なし 32 ビット整数 (15 億エントリ) があります。それらをファイルに書き込んで、メインメモリに読み戻す必要があります。

今、私はそれを使用してそれを行います:

ofstream ofs;
ofs.open(filename);
for (uint64_t i = 0 ; i < 1470000000 ; i++)
ofs << integers << " " ;

ifstream ifs;
ifs.open(filename);
for (uint64_t i = 0 ; i < 1470000000 ; i++)
ifs >> integers ;

この実行には数分かかります。誰でも私を助けることができますか、より高速な方法でそれを行うライブラリメソッドはありますか? または何か提案があれば、パフォーマンス テストを実行できますか? mmap(Linuxで)上記を実行するために使用する簡単なC++コードを誰か教えてもらえますか?

編集: 事例

#include<iostream>
#include <stdint.h>
#include <cstdio>
#include <cstdlib>
#include <sstream>

using namespace std;

main()
{
      uint32_t* ele = new uint32_t [100] ;
      for(int i = 0; i < 100 ; i++ )
      ele[i] = i ;

      for(int i = 0; i < 100 ; i++ ){
          if(ele[i] < 20)
          continue ;
          else
          // write  ele[i] to file
          ;   
      }

 for(int i = 0; i < 100 ; i++ ){
          if(ele[i] < 20)
          continue ;
          else
          // read  number from file
          // ele[i] = number * 10 ;
          ;   
      }

     std::cin.get();
}
4

4 に答える 4

3

最初にすべきことは、時間がどこに向かっているのかを判断することです。テキストの書式設定と解析は簡単ではなく、時間がかかる場合がありますが、ファイルのサイズを考えると、実際の書き込みと読み取りには時間がかかります。2 番目のことは、データがどの程度「移植可能」でなければならないかを判断することです。最速の解決策は、ほぼ確実に mmap、配列をファイルに直接 (または Windows で同等の方法で) 読み書きしないことです。ただし、これは移植可能な表現を提供しません。また、コンパイラをアップグレードしても、データが読み取れなくなる可能性があります。(今日の 32 ビット整数ではありそうにありませんが、過去には発生していました)。

一般的に、読み書きに時間がかかる場合は、 を使用して調査することをお勧めしますmmap。フォーマットと解析を行う場合は、ある種のバイナリ形式を調査する必要があります。これにより、結果のファイルが小さくなれば、読み取りと書き込みにも役立つ可能性があります。通常のネットワーク標準を使用して値を書き込む最も単純なバイナリ形式では、次のものしか必要ありません。

void
writeInt( std::ostream& dest, int32_t integer )
{
    dest.put( (integer >> 24) & 0xFF );
    dest.put( (integer >> 16) & 0xFF );
    dest.put( (integer >>  8) & 0xFF );
    dest.put( (integer      ) & 0xFF );
}

int32_t
readInt( std::istream& source )
{
    int32_t results = 0;
    results  = source.get() << 24;
    results |= source.get() << 16;
    results |= source.get() <<  8;
    results |= source.get();
    return results;
}

(明らかに、いくつかのエラー チェックを追加する必要があります。)

整数の多くが実際に小さい場合は、Google Protocol Buffers で使用されているような可変長エンコーディングを試すことができます。ほとんどの整数が -64...63 の範囲にある場合、ファイルのサイズが 4 分の 1 になる可能性があります (これにより、読み書きに必要な時間が改善されます)。

于 2013-01-23T09:13:10.863 に答える
2

サイズがわかっている場合は、配列をfwrite/freadするだけです。

于 2013-01-23T09:14:44.727 に答える
2

入力ストリームと出力ストリームの両方に大きなバッファを使用すると、パフォーマンスが向上する可能性があります。

ofstream ofs;
char * obuffer = new char[bufferSize];
ofs.rdbuf ()->pubsetbuf (obuffer, bufferSize);
ofs.open (filename);

ifstream ifs;
char * ibuffer = new char[bufferSize];
ifs.rdbuf ()->pubsetbuf (ibuffer, bufferSize);
ifs.open (filename);

またifs >> integers ;、整数のみを解析する方法もかなり遅いです。行を読み取ってから、std::strtol()それらを解析するために使用してみてください。IME、それは測定可能なほど高速です。

于 2013-01-23T09:18:59.117 に答える
0

コピーしたいだけの場合は、それを使用してパフォーマンスを向上させることができます。

std::ifstream  input("input");
std::ofstream  output("ouptut");
output << input.rdbuf();

または、バッファサイズを設定すると速度が向上する場合があります。

char cbuf[buf_size];
ifstream fin;
fin.rdbuf()->pubsetbuf(cbuf,buf_size);

ストリームのパフォーマンスに影響を与える理由がわからないため、回答で long int の問題を考慮しませんでしたが、とにかく役立つことを願っています。

于 2013-01-23T09:24:12.557 に答える