- ベストアンサー
Windows Vista、7でのマルチスレッドのパフォーマンスの低下
Windows Vista、7でのマルチスレッドのパフォーマンスの低下について WIN32で多数のスレッドが動作するプログラムを、Windows Vistaまたは7で動かすと、 Windows XPで動かす場合に比べて、10倍以上時間がかかります。 この原因として、何か考えられることはありますか?
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
>この結果、実行時間はXPと同じ程度に早くなりました。 >クリティカルセクションから抜けたスレッドがタイムスライスを譲ることで >プログラム全体が高速になるのは、どのような理屈からなのでしょうか? その箇所はwhile文やfor文の中にありませんでしたか? だとするとビジーループに陥ってた可能性があります。(CPU使用率があるコアで100%になっていませんでしたか?) while(true) { EnterCriticalSection( &CriticalSection ); ・・・・ LeaveCriticalSection( &CriticalSection ); } というコードであれば EnterCriticalSectionで処理が止まらない限り このスレッドがタイムスライスを使い切るまでCPUリソースを占有してしまいます。 (ほかのスレッドに切り替わったところで、このスレッドの順になればまたタイムスライスを使い切るまで占有します →結果このスレッドがほとんどのCPUリソースを食うことになる。) ビジーループはシステム全体に悪影響を与えます。たとえば、ウィンドウズのメッセージ処理さえ止めてしまいます。 (クリックしても反応がにぶくなる等の現象が起きます) Xpで起きなかった原因については ・タイムスライスの設定値等の違い ・バックグラウンドで動いているプロセスによる影響 ・OSによるタスク管理の違い、 等が考えられますが正確にはわかりません。
その他の回答 (2)
- sha-girl
- ベストアンサー率52% (430/816)
>まず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で軽かったのは論理コア数が少なくてビジーループが起きなかったのではという理由な気がしますがどうでしょう)
お礼
回答ありがとうございました。 肝心なことを書き忘れていました。 同一のパソコンにXP、Vista、7を入れて確認しています。 while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ){ TranslateMessage( &msg ); DispatchMessage( &msg ); Sleep(10); } についてはSleep(10)でブレークポイントを設定しましたが停止しなかったので、 sleep(10)のwhileループの外に出して必ず実行されるようにしてみましたが、 現象は変わりませんでした。 >論理コア数が少なくてビジーループが起きなかった 論理コアという言葉すら知りませんでした。 勉強して、解決への糸口に致します。
補足
恐縮ですが、1つ質問してよろしいでしょうか? プログラムの中で、8つのサブスレッドが共通のクリティカルセクションを持っており、 どうも、そこで渋滞しているようなので、 クリティカルセクションの直後にSpeed(10)を入れてみました。 (クリティカルセクション内の実行時間は、シングルスレッドで走らせて2~3msくらい) EnterCriticalSection( &CriticalSection ); ・・・・ LeaveCriticalSection( &CriticalSection ); Sleep(10); この結果、実行時間はXPと同じ程度に早くなりました。 クリティカルセクションから抜けたスレッドがタイムスライスを譲ることで、 プログラム全体が高速になるのは、どのような理屈からなのでしょうか?
- hidebun
- ベストアンサー率50% (92/181)
10倍というのが、どのぐらいの時間についてのことなんでしょう? 例えばXPで10秒で終わる処理がVista、7では100秒かかったりするのでしょうか。 こんな記事はありますが、10倍というのは、パフォーマンスの低下が甚だしいですね。 http://www.computerworld.jp/topics/mcore/133949-1.html
お礼
回答ありがとうございます。 >例えばXPで10秒で終わる処理がVista、7では100秒かかったりするのでしょうか その通りです。 XPで20秒くらいで終わるプログラムが、Vista, 7で数分かかります。 メインスレッドが8個のサブスレッドを起動して、 全サブスレッドの終了をループで待機するプログラムです。 各サブスレッドも、USBデバイスのステータスをループで監視しています。 9スレッド全て、ループの中で次のメッセージ処理をしていますが、 これを除いても結果は変わりません。 while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ){ TranslateMessage( &msg ); DispatchMessage( &msg ); }
お礼
いろいろお世話になりました。 ありがとうございました。