プロが教える店舗&オフィスのセキュリティ対策術

Windows Vista、7でのマルチスレッドのパフォーマンスの低下について

WIN32で多数のスレッドが動作するプログラムを、Windows Vistaまたは7で動かすと、
Windows XPで動かす場合に比べて、10倍以上時間がかかります。
この原因として、何か考えられることはありますか?

A 回答 (3件)

>この結果、実行時間はXPと同じ程度に早くなりました。


>クリティカルセクションから抜けたスレッドがタイムスライスを譲ることで
>プログラム全体が高速になるのは、どのような理屈からなのでしょうか?
その箇所はwhile文やfor文の中にありませんでしたか?
だとするとビジーループに陥ってた可能性があります。(CPU使用率があるコアで100%になっていませんでしたか?)

while(true)
{
EnterCriticalSection( &CriticalSection );
・・・・
LeaveCriticalSection( &CriticalSection );
}

というコードであれば
EnterCriticalSectionで処理が止まらない限り
このスレッドがタイムスライスを使い切るまでCPUリソースを占有してしまいます。
(ほかのスレッドに切り替わったところで、このスレッドの順になればまたタイムスライスを使い切るまで占有します
→結果このスレッドがほとんどのCPUリソースを食うことになる。)
ビジーループはシステム全体に悪影響を与えます。たとえば、ウィンドウズのメッセージ処理さえ止めてしまいます。
(クリックしても反応がにぶくなる等の現象が起きます)

Xpで起きなかった原因については
・タイムスライスの設定値等の違い
・バックグラウンドで動いているプロセスによる影響
・OSによるタスク管理の違い、
等が考えられますが正確にはわかりません。
    • good
    • 0
この回答へのお礼

いろいろお世話になりました。
ありがとうございました。

お礼日時:2010/11/12 09:37

>まずWindows Vistaまたは7で動かすと、


Windows XPとWindows Vista/7はこれらは同じマシンスペックでしょうか?
コア数やHTの挙動が影響している可能性があります。

基本的に原因は地道に調べていくしかありません。(外部のプロファイラを使うのも手です。Intel Parallel Studio 2011等)
まずはどれぐらいCPUがロックされているか調べてみてください。
Windowsなら、CriticalSection、CreateMutex、CreateSemaphore、Interlock~によるスピンロック等がありますが
それらを使ってロックしている箇所がCPUリソースの何パーセント占有しているか
QueryPerformanceCounter、QueryPerformanceFrequency 等を使って調べてみてください。
http://support.microsoft.com/kb/172338/ja
※Windowsにおけるマルチスレッドプログラミングでパフォーマンスを上げるには
 Interlock~を使っていかにロックレスにするかが重要です。


ところで「回答へのお礼」に書かれた
「while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ){」
が ビジーループしているんじゃないでしょうか?

while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ){
  TranslateMessage( &msg );
  DispatchMessage( &msg );
  Sleep(10);
}

とするだけで多少改善するかもしれません。

while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )を9スレッドで回す部分は見直した方がよいかも。
PeekMessageやGetMessageを複数スレッドで別HWNDを参照するならともかくHWND指定無しで使うというのは
見たことがありませんし効果的だとも思えません。。
(Xpで軽かったのは論理コア数が少なくてビジーループが起きなかったのではという理由な気がしますがどうでしょう)

この回答への補足

恐縮ですが、1つ質問してよろしいでしょうか?

プログラムの中で、8つのサブスレッドが共通のクリティカルセクションを持っており、
どうも、そこで渋滞しているようなので、
クリティカルセクションの直後にSpeed(10)を入れてみました。
(クリティカルセクション内の実行時間は、シングルスレッドで走らせて2~3msくらい)

EnterCriticalSection( &CriticalSection );
・・・・
LeaveCriticalSection( &CriticalSection );
Sleep(10);

この結果、実行時間はXPと同じ程度に早くなりました。
クリティカルセクションから抜けたスレッドがタイムスライスを譲ることで、
プログラム全体が高速になるのは、どのような理屈からなのでしょうか?

補足日時:2010/11/01 15:17
    • good
    • 0
この回答へのお礼

回答ありがとうございました。

肝心なことを書き忘れていました。
同一のパソコンにXP、Vista、7を入れて確認しています。

while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ){
  TranslateMessage( &msg );
  DispatchMessage( &msg );
  Sleep(10);
}

についてはSleep(10)でブレークポイントを設定しましたが停止しなかったので、
sleep(10)のwhileループの外に出して必ず実行されるようにしてみましたが、
現象は変わりませんでした。

>論理コア数が少なくてビジーループが起きなかった
論理コアという言葉すら知りませんでした。
勉強して、解決への糸口に致します。

お礼日時:2010/10/29 20:10

10倍というのが、どのぐらいの時間についてのことなんでしょう?


例えばXPで10秒で終わる処理がVista、7では100秒かかったりするのでしょうか。

こんな記事はありますが、10倍というのは、パフォーマンスの低下が甚だしいですね。
http://www.computerworld.jp/topics/mcore/133949- …
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

>例えばXPで10秒で終わる処理がVista、7では100秒かかったりするのでしょうか

その通りです。
XPで20秒くらいで終わるプログラムが、Vista, 7で数分かかります。

メインスレッドが8個のサブスレッドを起動して、
全サブスレッドの終了をループで待機するプログラムです。
各サブスレッドも、USBデバイスのステータスをループで監視しています。

9スレッド全て、ループの中で次のメッセージ処理をしていますが、
これを除いても結果は変わりません。

while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ){
  TranslateMessage( &msg );
  DispatchMessage( &msg );
}

お礼日時:2010/10/29 18:31

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!