4

ユーザー定義の数のスレッドを使用して処理を行うベンチマーク アプリケーションに取り組んでいます。また、ベンチマーク結果のビジュアライザー アプリケーションにも取り組んでいます。

ベンチマーク自体は C++ で作成されており (スレッド化には pthread を使用しています)、ビジュアライザーは Python で作成されています。

現在、2 つの話をするために私が行っているのはstdout、ベンチマークからビジュアライザーへのパイプです。netcatこれには、あるマシンでベンチマークを実行し、別のマシンでビジュアライザーを実行するようなツールを使用できるという利点があります。

アプリケーションの概要図

ベンチマークについて少し:

  • それは非常にCPUバウンドです
  • 各スレッドは、数十ミリ秒ごとに重要なデータ (つまり、ビジュアライザーに必要なデータ) を書き込みます。
  • 印刷される各データムは、5 ~ 20 文字の行です。
  • 前述のように、スレッドの数は非常に多様です (1、2、40 など)。
  • データが壊れていないことは重要ですが (たとえば、あるスレッドがprintf/の実行中に別のスレッドをプリエンプトcoutし、印刷されたデータが別のスレッドの出力とインターリーブされるなど)、書き込みが正しい方法で行われることはそれほど重要ではありません。注文。

最後のポイントに関する例:

// Thread 1 prints "I'm one\n" at the 3 seconds mark
// thread 2 prints "I'm two\n" at the 4 seconds mark

// This is fine
I'm two
I'm one

// This is not
I'm I'm one
 two

ベンチマークでは、異なるスレッドの出力間のインターリーブの可能性を最小限に抑えるために、(2) にstd::cout近いprintfためから に切り替えました。write

stdoutスレッド数が増えると複数スレッドからの書き込みがボトルネックになるのではないかと心配です。結果をゆがめないように、ベンチマークの視覚化のための出力部分のリソースが非常に少ないことが非常に重要です。

ベンチマークのパフォーマンスに絶対に不可欠なもの以上に影響を与えることなく、2 つのアプリケーションを対話させる効率的な方法についてのアイデアを探しています。何か案は?以前にこのような問題に取り組んだ人はいますか? よりスマートでクリーンなソリューションはありますか?

4

4 に答える 4

3

stdout への書き込みが、実際の問題のパフォーマンスのボトルネックになる可能性はほとんどありません。そうである場合は、ログを取りすぎているか、バックグラウンド ノイズに対して測定できないほど高速なタスクのベンチマークを行っています。ただし、これはスレッドセーフのバグです。printf と cout の選択はただのブードゥーです。どちらもスレッドセーフではありません。マルチスレッド環境でバッファリングされた I/O を使用する場合は、呼び出しを自分でシリアル化する必要があります ( を使用するpthread_mutex_tか、セマフォを使用してキューを実装するなど...)。これを行うためにシステム コールの原子性に依存したい場合 (内部的には、カーネルがまったく同じ種類のシリアライゼーションを行います)、システム コールを自分で行う必要があり、printf が書き込みに「近い」ことに依存する必要はありません。

于 2012-08-29T17:08:23.057 に答える
0

それらはすべて、出力の行を文字列としてキューにプッシュし、別のスレッドがそれらをプルしてログに記録することができます(シングルスレッド、バッファリングされた出力、フラッシュの頻度は低くなります)。

于 2012-08-29T17:08:05.900 に答える
0

POSIX 準拠の stdlib があると仮定すると、stdio 関数への各呼び出しは他のスレッドに対してアトミックであるため、1 回のprintf呼び出しで行を出力する限り、2 つのスレッドが行を書き込んでも、それらが混ざり合うことはありません。まったく同時に。C++ での呼び出しごとに同じiostream::operator<<ことが言えますが、 のようなものを書くcout << "xxx " << var << endl;と、1 回ではなく 3 回の呼び出しになります。

stdio 関数への複数の呼び出しを使用し、それを単一のユニットとして記述したい場合は、flockfile(3) を使用できます。例えば:

flockfile(stdout);
printf("data: ");
print_struct(foo);  // a function that calls printf internally
printf("\n");
funlockfile(stdout);

これにより、data他のスレッドがインターリーブすることを許可せずに、改行までのすべてが出力されます。C++ iostream でも役立ちます。

flockfile(stdout);
cout << "data: " << x << endl;
funlockfile(stdout);
于 2012-08-29T17:24:28.610 に答える
0

まず、心配する前に、それが問題であることを確認します。書き込みが 10 ミリ秒または 20 ミリ秒ごとに 1 回だけの場合は、何も問題にならない可能性があります。

それ以外の場合: 「書き込み」は実際には 2 つの操作で構成されます: 出力のフォーマットと、フォーマットされたバイトの物理的な出力です。2 つ目は、プロセスから OS に 5 ~ 20 文字をコピーするだけなので、おそらくかなり高速です。(OS はwrite/WriteFile関数から戻ると、物理的な書き込みを行います。) std::ostrstream(非推奨ですが、利用できるはずです) またはを使用snprintfしてローカルでフォーマットする場合、 local にフォーマットしてから、結果に対してorをchar[]呼び出し ます。外部同期は必要ありません。writeWriteFile

別の方法として、すべての書き込みを別のスレッドで実行し、要求を (必要なデータと共に) キュー (条件変数を使用して簡単に実装できます) にプッシュすることもできます。

于 2012-08-29T17:13:15.607 に答える