2

小さなプログラムを PHP から C++ に書き直しています。アイデアは、基本的に SSD 上の 32Gb ファイルを読み込んで、いくつかの簡単な操作を実行することです。

x64 リリース ビルドで Visual Studio 2012 を使用しています。PHP は 5.3 32bit です。

問題は、PHP の素の読み取り速度が C++ よりも速いことであり、これは私を本当に困惑させます。PHP は ~350 Mb/秒、C++/ifstream コードは 180 Mb/秒です。

コードはとてもシンプルです:

ifstream datafile("data.txt", ios::binary);

while(datafile.read((char*)buffer, data_per_chunk)) {
//  do stuff;

最大 16Mb までのさまざまなバッファ サイズを試しましたが、ほとんど違いはありませんでした。また、datafile.rdbuf()->pubsetbuf(...) を介して内部バッファーを設定しようとしましたが、違いはありませんでした。

古代の C レベル インターフェイスに戻らずに ifstream を高速化する方法に関するヒントはありますか? 少なくとも PHP レベルのパフォーマンスに到達したいと考えています。多分いくつかの凝った先読み/キャッシュ設定か何か。

メモリマップされたファイルが役立つ可能性が高いことは理解していますが、ファイルが物理 RAM よりも大幅に大きく、4Gb よりも大きいことを考えると、物事を単純に保つことができる場合、ifstream の設定を微調整することをお勧めします。つまり、潜在的な 32 ビット ビルドには使用できません。 .

4

2 に答える 2

5

ifstream でも最大の SSD 読み取り速度に到達できるようです。

これを行うには、CPU の L2 キャッシュに適切に適合させながら、内部の ifstream readbuffer を ~2Mb に設定する必要があります。これは、SSD の読み取り速度のピークが発生する場所です。次に、内部バッファよりも小さいチャンクでデータを読み取る必要があります。8 ~ 16kB のチャンクでデータを読み取ると最良の結果が得られましたが、1Mb のチャンクで読み取るよりも約 1% しか高速ではありません。

ifstream 内部バッファの設定:

ifstream datafile("base.txt", ios::binary);
datafile.rdbuf()->pubsetbuf(iobuf, sizeof iobuf);

これらすべての調整により、M500 480Gb SSD の理論上の最大値に近い 495 Mb/秒の読み取り速度が得られました。実行中の CPU 負荷は 5% でした。これは、ifstream 実装のオーバーヘッドによって実際に制限されなかったことを意味します。

ifstream と std::basic_filebuf の間に目に見える速度の違いは見つかりませんでした。

于 2013-10-18T19:12:23.427 に答える
1

ifstreamすべてをバッファに読み込んでいるときに使用する意味がわかりません。どちらかbasic_filebufまたは「古代」の C インターフェイスが機能します。最初に C インターフェイスと比較する必要がありifstreamます。これにより、実際に問題があることがわかりますifstream

パフォーマンスが向上する順に、次のオプションが表示されます。

  • std::ifstream:readなど
  • std::basic_filebuf: opensgetnなど
  • C : fopenfreadなど
  • WinApi : CreateFile(ない OpenFile!)、ReadFileExなど。

おそらく、PHP は内部で C インターフェイスを使用していませんが、winapi を使用しており、それが違いの原因です。

于 2013-10-18T02:27:51.683 に答える