一見すると、これは、きれいではないが正しい C++ または C のように見えます (確認する簡単な方法は、コンパイルすることです)。インクルード ( <windows.h>
、<process.h>
、および<time.h>
) がありませんが、それ以外は正常にコンパイルされます。
clock
とSleep
はそれほど正確ではなく、Sleep
信頼性も高くないことに注意してください。ただし、平均して、スレッド関数は意図したとおりに機能するはずです (数パーセントの変動があります)。
while(1){}
ただし、質問 2) に関しては、最後をスピンではなくブロックするものに置き換える必要があります (たとえばWaitForSingleObject
、Sleep
そうする場合)。そうしないと、クアッドコアでプログラム全体の負荷が 50%になりません。メイン スレッドにより 1 つのコアに 100% の負荷がかかり、さらに 4 つのワーカーから 4x 50% の負荷がかかります。これは明らかに、コアあたり 50% を超えます (そして、スレッドが 1 つのコアから別のコアにバウンスし、厄介な副作用が発生します)。
タスク マネージャーまたは同様のユーティリティを使用して、必要な負荷が得られるかどうかを確認するのが適切なオプションです (これは最も簡単な解決策であり、最適な解決策でもあります)。
また、このような方法で負荷をシミュレートすることは、おそらくある程度は機能しますが、100% 信頼できるわけではないことに注意してください。
予測が難しい影響 (メモリ、実行ユニット) が存在する可能性があります。たとえば、このループで CPU の整数実行ユニットを 100% 使用しているが (合理的な仮定)、浮動小数点または SSE ユニットはゼロであると仮定します。最新の CPU は、実際のコアまたは論理コア間でリソースを共有する場合があり、どのような影響が得られるかを正確に予測できない場合があります。または、別のスレッドがメモリにバインドされているか、重大なページ フォールトが発生している可能性があるため、CPU 時間を取り除いても、思ったほど影響を受けません (実際には、プリフェッチの動作を改善するのに十分な時間を与える可能性があります)。または、AGP 転送でブロックされる可能性があります。または、あなたが言うことができない他の何か。
編集:
改善されたバージョン、いくつかの問題を修正し、意図したとおりに動作する短いコード:
clock_t
(これは、特別に 'd でない整数を使用clock
するよりも、技術的には「より正確」です。偶然にも、それがおそらく元のコードが意図したtypedef
とおりに機能しないまさにその理由です。 in は常に を評価するため、ワーカーはほぼ常にスリープ状態になり、CPU を消費しません。clock_t
if()
true
- コードが少なくなり、回転時の複雑な計算が少なくなります。50 ティック後のウェイクアップ時間を計算し、その時間に達するまでスピンします。
getchar
最後にプログラムをブロックするために使用します。これにより CPU 時間が消費されることはなく、 を押してプログラムを終了できますEnter。スレッドは通常のように適切に終了されませんが、この単純なケースでは、プロセスが終了するときに OS にスレッドを終了させるだけで問題ないでしょう。
- 元のコードと同様に、これは同じティック
clock
を使用することを前提としています。Sleep
これは確かに大胆な仮定ですが、元のコードで使用した Win32 でも当てはまります (両方の「ティック」はミリ秒です)。C++ には( 、または C++11Sleep
なしで) のようなものがないため、Windows 以外の移植性が意図されている場合は、とにかく再考する必要があります。boost::thread
std::thread
- 元のコードと同様に、不正確で信頼性の低い関数 (
clock
および)に依存しています。を使用せずに私のシステムで等しい。それにもかかわらず、プログラムは「ほぼ完璧」に動作し、私のマシンには 50% +/- 0.5% の負荷がかかります。Sleep
Sleep(50)
Sleep(63)
timeBeginPeriod
元のコードと同様に、これはスレッドの優先度を考慮していません。通常よりも優先順位の高いプロセスは、このスロットリング コードによってまったく影響を受けません。これは、Windows スケジューラがそのように機能するためです。
#include <windows.h>
#include <process.h>
#include <time.h>
#include <stdio.h>
void task1(void *)
{
while(1)
{
clock_t wakeup = clock() + 50;
while(clock() < wakeup) {}
Sleep(50);
}
}
int main(int, char**)
{
int ThreadNr;
for(int i=0; i < 4; i++) _beginthread( task1, 0, &ThreadNr );
(void) getchar();
return 0;
}