2

私はかなりの量を見回しましたが、私が探しているものを見つけることができないようです.

私が解決しようとしている問題の背景は次のとおりです。

名前付きパイプのように動作するメモリ マッピング ライブラリを作成しました。バイトを入れたり、そこからバイトを取得したり、読み取り/書き込みに使用できるバイト数を照会したりできます。

それを使用して通信する高速な (ほとんどの場合) プロセスは、8KB 以上のバイトのチャンクを渡す場合、平均 4GB/秒になります。チャンク サイズが 512B に近づくと、パフォーマンスは約 300MB/秒まで低下します。

問題:

非常にまれに、負荷の高いサーバーでは、非常に大きなラグ タイム (5 秒以上) が発生します。この問題の原因についての私の実行中の理論は、大規模な転送が行われている場合 (マップされたメモリのサイズよりも大きい場合)、データを書き込んでいるプロセスがタイト ポーリングを実行して、実装されている循環バッファーで使用可能なスペースが増えるのを待つことです。メモリマップの一番上。スリープの呼び出しがないため、ポーリング プロセスが正当な理由もなく CPU を占有している可能性があります。問題は、最小のスリープ呼び出し (1 ミリ秒) でさえ、パフォーマンスを完全に破壊することです。memmap のサイズは 16KB であるため、16KB ごとに 1ms スリープすると、パフォーマンスは 16MB/s の最良のシナリオまで低下します。

ソリューション:

CPU を放棄する呼び出し可能な関数が必要ですが、オペレーティング システム (この場合は Windows 7) によって再スケジュールされるタイミングに制限はありません。

誰か明るい代替案を持っていますか?/そのような機能が存在するかどうか知っていますか?

ありがとう。

4

5 に答える 5

3

MSDN のドキュメントによると、XP 以降でSleepは、タイムアウト 0 で呼び出すと、同じ優先度の他のプロセスに譲ります。

値が 0 の場合、スレッドは残りのタイム スライスを、実行の準備ができている同等の優先順位の他のスレッドに放棄します。実行する準備ができている同じ優先度のスレッドが他にない場合、関数はすぐに戻り、スレッドは実行を続けます。

http://msdn.microsoft.com/en-us/library/windows/desktop/ms686298(v=vs.85).aspx

より多くの作業が必要ですが、より確実に機能する別のオプションは、プロデューサー プロセスとコンシューマー プロセス間でイベント ハンドルを共有することです。を使用CreateEventしてイベントを作成DuplicateHandleし、それを他のプロセスに取得できます。プロデューサーがバッファーをいっぱいにするとResetEvent、イベント ハンドルを呼び出しWaitForSingleObject、それを使用して呼び出します。コンシューマが完全な共有バッファから一部のデータを削除すると、 が呼び出さSetEventれ、 で待機していたプロデューサが起動されWaitForSingleObjectます。

于 2013-08-21T01:14:32.313 に答える
1

std::this_thread::yield()おそらくあなたが望むことをします。ほとんどの実装では、 Sleep with 0 を呼び出すだけだと思います。

于 2013-08-21T01:15:56.663 に答える
1

バイナリ選択を誤って想定しています。睡眠は常に悪い考えであるため、あなたは今、常に忙しく待っています。

より良い解決策は、眠らずに数回試すことです. それでも失敗する場合 (マップがいっぱいで、他のスレッドが実行されていないため)、真のスリープを発行できます。これは十分にまれであるため、平均して数マイクロ秒スリープ状態になります。リアルタイム クロック ( RDTSC) をチェックして、タイムスライスを放棄する前にビジー待機に費やした時間を判断することもできます。

于 2013-08-21T09:28:14.320 に答える
0

.Net で操作している場合は、Thread::Yield()メソッドを調べることができます。

特定のシナリオでは役立つ場合とそうでない場合がありますが、タイムスライスの残りを放棄することをスケジューラーに通知する正しい方法です。

.Net より前の環境で実行している場合 (Windows 7 を使用している場合はありそうにないようです)、SwitchToThread()代わりに Win32 関数を調べることができます。

于 2013-08-21T01:11:43.537 に答える