3

これはパフォーマンス コンピューティングの質問だと思います。私はCでプログラムを書いていますが、これは通常RAMに完全に保存できるよりもはるかに多くの出力を生成します。stdout出力を;に単純に書き込むつもりです。そのため、画面に表示されるか、ファイルにリダイレクトされる可能性があります。問題は、RAM に格納されるデータに最適なバッファ サイズを選択する方法です。

出力データ自体は特に重要ではないので、ランダムな整数の大量のリストを生成しているとだけ言っておきましょう。

私は2つのスレッドを持つつもりです.1つはデータを生成してバッファに書き込み、もう1つはそのバッファをに書き込みますstdout. このようにして、出力の次のバッファの生成を開始できますが、前のバッファはまだ に書き込まれていstdoutます。

明確にするために、私の質問はmalloc()pthread_create()などの関数の使用方法に関するものではありません。私の質問は、最適なバッファサイズのためにバイト数 (512、1024、1048576) を選択する方法に関するものであり、最高のパフォーマンスが得られますか?

理想的には、最適なバッファー サイズを動的に選択できる方法を見つけて、プログラムがその時点で実行されているハードウェアに合わせて調整できるようにしたいと考えています。この問題に対する答えを探してみましたが、バッファ サイズに関するいくつかのスレッドが見つかりましたが、特にこの問題に関連するものは見つかりませんでした。したがって、私はいくつかの異なる視点を得て、自分でできるよりも良いものを考え出すことができることを期待して、質問として投稿したかっただけです.

4

5 に答える 5

6

設計と最適化を混在させるのは時間の無駄です。これは、標準的な間違いの上位の 1 つと考えられています。設計に損傷を与える可能性があり、実際にはあまり最適化されません。

プログラムを動作させ、パフォーマンスの問題の兆候がある場合は、それをプロファイリングして、実際に問題を引き起こしている部分を分析することを検討してください。

これは、アプリケーションのマルチスレッド化などの複雑なアーキテクチャの最適化に特に当てはまると思います。単一のイメージをマルチスレッド化することは、決してやりたくないことです。テストが不可能であり、再現性のないバグが発生しやすく、実行環境によって失敗が異なり、他の問題もあります。ただし、一部のプログラムでは、マルチスレッドの並列実行が機能のために必要であるか、必要なパフォーマンスを得るための 1 つの方法です。それは広く支持されており、基本的には必要悪である場合もあります。

あなたのようなプログラムがそれを必要とするという確固たる証拠がなければ、初期設計でそれを望んでいるものではありません。

並列処理の他のほとんどの方法 (メッセージ パッシング?) は、実装とデバッグがより簡単であり、いずれにせよ、OS の I/O システムで多くのことを取得しています。

于 2013-01-18T19:04:06.370 に答える
1

個人的には時間を無駄にしていると思います。

ファーストランtime ./myprog > /dev/null

今、使用します time dd if=/dev/zero of=myfile.data bs=1k count=12M

ddできる限り単純なプログラムであり、ファイルを非常に迅速に書き込みます。ただし、数ギガバイトの書き込みにはまだ少し時間がかかります。(私のマシンでは 12G に約 4 分かかります。これはおそらく世界最速のディスクではありません。/dev/null への同じサイズのファイルには約 5 秒かかります)。

bs=x count=yテスト実行のプログラム出力と同じサイズで、組み合わせが作成される場所でいくつかの異なる数値を試すことができます。しかし、非常に大きなブロックを作成すると、実際には時間がかかることがわかりました(書き込みごとに1MB-おそらく、OSがデータを書き込む前に1MBをコピーし、それを書き込んでから次の1MBをコピーする必要があるためです。ブロック (私は 1k と 4k をテストしました)、データをコピーするのにかかる時間が大幅に短縮され、実際には「書き込む前に何もせずに回転するディスク」が少なくなります)。

これらの時間をプログラムの実行時間と比較してください。ファイルへの書き込みにかかる時間はdd、プログラムがファイルに書き込むよりもはるかに短いですか?

あまり違いがない場合は、プログラムで /dev/null に書き込むのにかかる時間を見てください。それが違いの一部またはすべてを説明していますか?

于 2013-01-18T21:45:44.593 に答える
1

簡単な答え: 測定します。

長い回答: 私の経験からすると、事前に予測するのが難しい要因に大きく依存しています。一方、開始前にコミットする必要はありません。一般的なソリューションを実装するだけで、完了したら、いくつかのパフォーマンス テストを行い、最良の結果が得られる設定を行います。プロファイラーは、プログラムのパフォーマンスが重要な部分に集中するのに役立ちます。

私が見たところによると、最速のコードを生成するものは、多くの場合、最も単純で直接的なアプローチを最初に試みます。平均的なプログラマーより優れている点は、優れたパフォーマンス テストを作成するための非常に優れたテクニックを持っていることです。

経験がなければ、特定の罠に陥りがちです。たとえば、キャッシュ効果を無視したり、(おそらくアプリケーションで?!) IO 操作のコストを過小評価したりします。最悪の場合、全体のパフォーマンスにまったく貢献しないプログラムの部分を圧迫することになります。

元の質問に戻ります。

説明したシナリオ (1 つの CPU バウンド プロデューサーと 1 つの IO バウンド コンシューマー) では、そのうちの 1 つがボトルネックになる可能性があります (プロデューサーがデータを生成する速度が大きく変化しない限り)。どちらが速いかによって、全体の状況が根本的に変わります。

最初に、IO バウンドのコンシューマーがボトルネックであると仮定しましょう (それが stdout に書き込むか、ファイルに書き込むかは問題ではありません)。考えられる結果は何ですか?

データを生成するアルゴリズムを最適化してもパフォーマンスは向上しません。代わりに、書き込みパフォーマンスを最大化する必要があります。ただし、書き込みパフォーマンスはバッファー サイズにあまり依存しないと思います (バッファーが小さすぎる場合を除きます)。

逆に、生産者が制限要因である場合、状況は逆転します。ここでは、生成コードのプロファイリングを行い、アルゴリズムの速度を改善し、場合によってはリーダー スレッドとライター スレッド間のデータ通信を改善する必要があります。ただし、ほとんどの場合、バッファは空になるため、バッファ サイズは重要ではありません。

確かに、状況は私が説明したよりも複雑になる可能性があります。しかし、極端なケースではないという確信がない限り、バッファ サイズの調整にはまだ投資しません。構成可能なままにしておけば、問題ないはずです。後で他のハードウェア環境に再装着することは問題にならないと思います。

于 2013-01-18T19:05:03.993 に答える
0

There's no need to use buffering, the OS will automatically swap pages to the disk for you whenever necessary, you don't have to program that. The simples would be for you to leave in in RAM if you don't need to save the data, else you're probably better of saving it after generating the data, because it's better for the disk i/o.

于 2013-01-18T19:37:18.107 に答える
0

最近のほとんどの OS は、ディスクを RAM のバッキング ストアとして使用することに長けています。ヒューリスティックは OS に任せて、パフォーマンスのボトルネックが発生するまで、必要なだけのメモリを要求することをお勧めします。

于 2013-01-18T19:06:52.833 に答える