2

私は加速されたC++を読んでいて、著者は次のように書いています。

実行に時間がかかる可能性のあるプログラムを作成する場合は、適切なタイミングで出力バッファーをフラッシュすることが重要な習慣になります。そうしないと、プログラムの出力の一部が、プログラムが書き込みを行ってから表示されるまでの間に、システムバッファで長時間停止する可能性があります。

これらの概念のいずれかを誤解している場合は、訂正してください。

  • バッファ:入力または出力を一時的に保持するために使用されるランダムアクセスメモリのブロック。
  • フラッシング:特定の..ummに割り当てられていたランダムアクセスメモリを解放します。

私が見つけたこの説明があります:

出力デバイスをフラッシュするということは、先行するすべての出力操作をすぐに完了する必要があることを意味します。これは、オペレーティングシステムで使用される最適化手法であるバッファリングの問題に関連しています。大まかに言えば、オペレーティングシステムは、画面へのデータ送信に関連するコストを正当化するのに十分な量のデータがあると判断するまで、データを「スタンバイ」にする権利を留保します(通常は行使します)。ただし、場合によっては、プログラムで実行される出力操作がプログラムの実行の特定の時点で完了することを保証する必要があるため、出力デバイスをフラッシュします。

その説明から続けて、システムがバッファをフラッシュする原因となる3つのイベントを読みました。

  1. バッファがいっぱいになり、自動的にフラッシュされます
  2. ライブラリは、標準の入力ストリームから読み取るように求められる場合があります*は、次のような標準の入力ストリームです。std::cin >> name ;
  3. 3番目の機会は、明示的に指示する場合です。どのように明示的にそれを伝えるのですか?

私は以下を完全に把握しているようには感じませんが:

  • 出力バッファとは、単なるバッファおよび推定可能な他のタイプのバッファとは何ですか。
  • バッファをフラッシュすることの意味。単にラムをクリアすることを意味しますか?
  • 上記の説明で参照されている「出力デバイス」とは
  • そして最後に、このすべての後、あなたのバッファをフラッシュするのに適切な瞬間があります...それは心地よく聞こえません。
4

5 に答える 5

1

をフラッシュするには、マニピュレータstd::ostreamを使用します。std::flushすなわち

std::cout << std::flush;

std::endlすでにストリームをフラッシュしていることに注意してください。したがって、挿入を終了する習慣がある場合は、追加の操作を行う必要はありません。これは、フラッシュが多すぎるためにパフォーマンスが低下している場合は、挿入std::endlから改行の挿入に切り替える必要があることに注意してください'\n'

ストリームは文字のシーケンスです(つまり、タイプのものchar)。出力ストリームは、文字を書き込むストリームです。一般的なアプリケーションは、ファイルへのデータの書き込み、画面へのテキストの印刷、またはファイルへの保存ですstd::string

ストリームには、一度に1024文字を書き込む方が、一度に1文字を1024回書き込むよりも桁違いに(またはそれ以上!)高速であるという機能がよくあります。「バッファリング」の概念の主な目的の1つは、これを便利な方法で処理することです。実際に文字を移動させたいものに直接書き込むのではなく、代わりにバッファに書き込みます。次に、準備ができたら、バッファを「フラッシュ」します。文字をバッファから必要な場所に移動します。または、正確な詳細を気にしない場合は、自動的にフラッシュするバッファーを使用します。たとえば、で使用されるバッファstd::ofstreamは通常固定サイズであり、いっぱいになるとフラッシュされます。

フラッシュするのに適した時期はいつですか?私はあなたが時期尚早に最適化していると言います。:)フラッシュするのに最適な瞬間を探すのではなく、頻繁に行ってください。十分な数のフラッシュを入れて、たとえばファイル内のデータを確認したいが、データがバッファに書き込まれずに置かれている状況に陥らないように、十分な頻度でフラッシュします。次に、実際にフラッシュが多すぎてパフォーマンスが低下していることが判明した場合は、それを調査することに時間を費やします。

于 2012-05-30T07:53:06.500 に答える
0

質問を1つずつ取り上げます。

  • 一般に、バッファは、データを一時的に保持するために使用されるメモリのブロックにすぎません。`std :: ofstream`に書き込む場合、文字は` std :: filebuf`に送信されます。これは通常、デフォルトでは、システムにすぐに出力されるのではなく、単にバッファに入れられます。`std :: ofstream`を使用する場合、実際には2つのバッファが使用されます。1つは` ofstream`(プロセス内)にあり、もう1つはOSにあります。
  • 標準では、基になるデータを外部サポート上の文字のシーケンスとして記述し、バッファはそのシーケンスへのウィンドウを表します。データの出力はバッファ内の画像のみを更新する可能性があり、フラッシュはバッファ内の画像をOSが持つデータの画像と「同期」させます。これは、実際のファイルに出力する場合はかなり適切な説明ですが、OSがの「イメージ」を維持しないシリアルポートなどに直接出力する場合は、実際には適合しません。データ。基本的に、OSに転送されていないストリームにデータを書き込んだ場合、バッファをフラッシュするとそのデータがOSに転送されます(つまり、 `ofstream`はバッファメモリを再利用してさらにバッファリングできます)。通常、バッファをフラッシュします(つまり 私が知っているすべての実装で)OSとのみ同期します(これは標準で必要なすべてです)。データが実際にディスクに書き込まれたことを保証するものではありません。アプリケーションによっては、これが問題になる場合とそうでない場合があります。
  • 「出力デバイス」とは、システムが望むものです。ファイル、画面上のウィンドウ、または古い時代やより単純なシステムでは、プリンタまたはシリアルポート。また、引用する説明は非常に誤解を招く可能性があります(つまり、「ofstream」について話しているわけではありません)。「ofstream」をフラッシュしても、先行するすべての出力操作が完全に終了するわけではないためです。ストリームバッファ内のデータがOSに転送(同期)されていることを確認するだけです。ほとんどの場合(少なくともWindowsとUnixでは)、これはすべて、データが(プロセス内の)あるバッファーから(OS内の)別のバッファーに移動されたことを意味します。
  • 適切な瞬間は、アプリケーションが何をしているかに大きく依存します。原則として、頻繁にフラッシュすることをお勧めします。そうすれば、プログラムがクラッシュした場合に、プログラムがどこまで進んだかを多かれ少なかれ確認できます。(`std :: endl`フラッシュを出力することを忘れないでください。最も単純な使用法では、`'\n'`の代わりに`std :: endl`を使用するだけで十分です。)もっと考えたい場合が少なくとも2つあります。ただし、フラッシングについて。ブロック内に非常に大量のデータを出力している場合(つまり、出力間でフォーマットする以上のことを行わない場合)、過度のフラッシュは出力を大幅に遅くする可能性があります。このような場合は、 `std::endl`の代わりに`'\n'`の使用を検討することをお勧めします。もう1つは、データをすぐに表示したいロギングなどの場合です。

std::ostream::flush()または を呼び出すと、データは明示的にフラッシュされますstd::ofstream::close()。(もちろん、後者の場合、後でそれ以上データを書き込むことはできません。)

データはフラッシュされるまで実際には「書き込まれない」ため、それまではほとんどのエラーを検出できないことにも注意してください。特に、次のようなものです。

if ( output << data ) {
    //  succeeded...
}

実際には機能しません。によって報告される「成功」はofstream、文字をバッファに正常にコピーしたことだけです(失敗することはほとんどありません)。

データの大きなブロックを中断せずに書き込むときの通常のイディオムは、フラッシュせずにデータを書き込むだけで、ファイルを閉じてエラーをチェックすることです。これは、データをすぐに表示したい場合に割り込みを使用して書き込む場合には適切ではありません。また、プログラムがクラッシュすると、「書き込んだ」データの一部が消えてしまい、デバッグが困難になる可能性があるという欠点があります。

于 2012-05-30T08:19:37.463 に答える
0

これはアプリケーションのタイプに大きく依存しますが、経験則の1つは、1つのレコードを書き込んだ後にフラッシュすることです。通常はすべての行の後にあるテキストの場合、すべてのオブジェクトの後にあるバイナリデータの場合。パフォーマンスが遅いと思われる場合は、書き込んだすべてのXレコードをフラッシュし、パフォーマンスに満足できる数値が見つかるまでXを試してみてください。ただし、Xが十分に大きくないため、次の場合にデータが失われます。クラッシュ。

于 2012-05-30T05:58:59.367 に答える
0

著者はストリームバッファを意味していると思います。バッファをフラッシュする適切なタイミングは、実際には、コードの動作、コードの構築方法、バッファの割り当て方法、およびおそらく初期化されたスコープに依存します。

ストリームバッファと出力バッファについては、これを見てください。

はい、標準の入力ストリームとは、>>演算子を使用することを意味します。(多くの場合)

たとえばofstream::flush、他のタイプのバッファには独自の明示的なフラッシュメソッドがあり、手動での実装が必要な場合もあります。

于 2012-05-30T06:08:36.303 に答える
0

ストリームを明示的にフラッシュしますyour_stream.flush();

出力バッファとは、単なるバッファおよび推定可能な他のタイプのバッファとは何ですか。

バッファは通常、処理を待機しているデータを保持するために使用されるメモリのブロックです。典型的な使用法の1つは、ストリームから読み取られたばかりのデータ、またはディスクへの書き込みを待機しているデータです。いずれにせよ、一度に大きなデータブロックの読み取り/書き込みを行う方が一般的に効率的であるため、一度にバッファ全体を読み取り/書き込みできますが、クライアントコードは、都合のよい量(たとえば、1文字または1文字)で読み取り/書き込みを行うことができます。一度に1行ずつ)。

バッファをフラッシュすることの意味。単にラムをクリアすることを意味しますか?

場合によります。入力バッファの場合、はい、通常はバッファの内容をクリアし、バッファに読み込まれたデータを破棄することを意味します(ただし、通常はRAMをクリアしません。内部の簿記を設定するだけです。バッファが空です)。

出力バッファの場合、通常、バッファをフラッシュするということは、バッファにあるすべてのデータを関連するストリームにすぐに書き込むように強制することを意味します。

上記の説明で参照されている「出力デバイス」とは

データを書き込んでいるとき、それは最終的に書き込んでいるデバイスです。これは、ディスクや画面などのファイルである可能性があります。

そして最後に、このすべての後、あなたのバッファをフラッシュするのに適切な瞬間があります...それは心地よく聞こえません。

明らかな好機の1つは、しばらくの間データの書き込みを終了し、しばらくの間(少なくとも同じ宛先に)出力を生成しない処理(またはその他)に戻るときです。直後に同じ場所に移動するデータをさらに生成する可能性がある場合は、バッファーをフラッシュする必要はありませんが、目立った遅延が発生する前にデータをバッファーに残したくない場合もあります。データが宛先に書き込まれるように、バッファ(またはその他)を埋めます。

于 2012-05-30T06:21:05.547 に答える