2

C#にポーリングループがあり、平均 して100マイクロ秒ごとにポーリングする必要があります<EDIT>(もちろん、コア不足のためにWindowsによって実行される過度のプリエンプティブスレッドコンテキストスイッチがない場合)</EDIT>

スケジュールを変更する時間がないため、Sleep(1)はスケジュールを変更しません。

そこで、スレッド(実際にはアフィニティを設定するときのコア)を専用にし、各反復の一連のサイクルにThread.SpinWaitを使用することにしました。これは正常に機能しますが、不必要な量の電力を消費します。100マイクロ秒は、CPUが一時停止するのに十分です(Windowsのタイムスライスが長くなるため、スレッドをスケジューラーから一時的に削除するのに十分ではありません)。

代わりに、Intel PAUSE命令を使用することを考えていましたが、IntelCPUがハードウェアスレッドを一時停止するトリガーになるかどうかはわかりません。Intelは、電力を維持し、スピンループで使用する必要があると主張していますが、一時停止は100マイクロ秒にもなるため、コアをC1モードでスリープ状態にする必要があります。

何か案は?

編集:サードパーティのAPIをポーリングしているので、ブロックする同期イベントはありません。

4

2 に答える 2

2

当然、同期プリミティブとタイマーを使用することは、CPU/電力を大量に消費するビジー待機を回避するための推奨される方法です。ただし、頻繁にポーリングする必要がある場合は、少なくともユーザーモードでは、従来の方法でこれを実現する方法はありません。

簡単なことの1つはpause、ループ内にCPU命令を含めることです。MSVCでは、組み込みのYieldProcessor()方法で実装されます。

これを超えて-おそらくカーネルモードプログラミングのみ。そこでは、高精度のマルチメディアタイマーを使用できます。

編集:

についてSetWaitableTimer。これはオプションかもしれません。「従来の」Win32待機関数(など)とは異なりSleepWaitForSingleObjectパラメータとして高精度のタイムアウトを使用します。

ただし、ユーザーモードタイマーは本質的に非同期です。タイマーが高精度でアクティブになると仮定しましょう(これは明らかではありませんが、「従来の」Win32待機関数は、数十ミリ秒のオーダーのティッククォンタムまで正確です)。タイマーがアクティブになると、適切な待機中のスレッドが解放されます。ただし、スレッドスケジューラは、このスレッドをすぐに実行にアタッチする必要はありません。次のタイムスライスを待機する場合があります。または、同時スレッドがある場合は、スレッドの実行をさらに遅らせることもできます。

結論として、このアイデアは試す価値があるようです。しかし、これが多かれ少なかれを使用するのと同等であるとしても、私は驚かないでしょうSleep

于 2012-08-07T13:25:38.643 に答える
2

待機時間が長いため、SSE3メモリ領域モニターは省電力の点ではるかに効率的であることがわかりますが、実際にはブロッキングスピン待機としてではなく、アラート可能待機として設計されていますが、それでも実行可能な代替手段となる可能性があります。

_mm_mwaitただし、これをC#で取得するには、C ++組み込み関数(および)へのインターフェイスを提供する外部DLLが必要です_mm_monitor

于 2012-08-07T14:14:55.320 に答える