• ベストアンサー

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

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

質問者が選んだベストアンサー

  • ベストアンサー
  • sha-girl
  • ベストアンサー率52% (430/816)
回答No.3

>この結果、実行時間はXPと同じ程度に早くなりました。 >クリティカルセクションから抜けたスレッドがタイムスライスを譲ることで >プログラム全体が高速になるのは、どのような理屈からなのでしょうか? その箇所はwhile文やfor文の中にありませんでしたか? だとするとビジーループに陥ってた可能性があります。(CPU使用率があるコアで100%になっていませんでしたか?) while(true) { EnterCriticalSection( &CriticalSection ); ・・・・ LeaveCriticalSection( &CriticalSection ); } というコードであれば EnterCriticalSectionで処理が止まらない限り このスレッドがタイムスライスを使い切るまでCPUリソースを占有してしまいます。 (ほかのスレッドに切り替わったところで、このスレッドの順になればまたタイムスライスを使い切るまで占有します →結果このスレッドがほとんどのCPUリソースを食うことになる。) ビジーループはシステム全体に悪影響を与えます。たとえば、ウィンドウズのメッセージ処理さえ止めてしまいます。 (クリックしても反応がにぶくなる等の現象が起きます) Xpで起きなかった原因については ・タイムスライスの設定値等の違い ・バックグラウンドで動いているプロセスによる影響 ・OSによるタスク管理の違い、 等が考えられますが正確にはわかりません。

_hitoshi_
質問者

お礼

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

その他の回答 (2)

  • sha-girl
  • ベストアンサー率52% (430/816)
回答No.2

>まず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で軽かったのは論理コア数が少なくてビジーループが起きなかったのではという理由な気がしますがどうでしょう)

_hitoshi_
質問者

お礼

回答ありがとうございました。 肝心なことを書き忘れていました。 同一のパソコンにXP、Vista、7を入れて確認しています。 while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ){   TranslateMessage( &msg );   DispatchMessage( &msg );   Sleep(10); } についてはSleep(10)でブレークポイントを設定しましたが停止しなかったので、 sleep(10)のwhileループの外に出して必ず実行されるようにしてみましたが、 現象は変わりませんでした。 >論理コア数が少なくてビジーループが起きなかった 論理コアという言葉すら知りませんでした。 勉強して、解決への糸口に致します。

_hitoshi_
質問者

補足

恐縮ですが、1つ質問してよろしいでしょうか? プログラムの中で、8つのサブスレッドが共通のクリティカルセクションを持っており、 どうも、そこで渋滞しているようなので、 クリティカルセクションの直後にSpeed(10)を入れてみました。 (クリティカルセクション内の実行時間は、シングルスレッドで走らせて2~3msくらい) EnterCriticalSection( &CriticalSection ); ・・・・ LeaveCriticalSection( &CriticalSection ); Sleep(10); この結果、実行時間はXPと同じ程度に早くなりました。 クリティカルセクションから抜けたスレッドがタイムスライスを譲ることで、 プログラム全体が高速になるのは、どのような理屈からなのでしょうか?

  • hidebun
  • ベストアンサー率50% (92/181)
回答No.1

10倍というのが、どのぐらいの時間についてのことなんでしょう? 例えばXPで10秒で終わる処理がVista、7では100秒かかったりするのでしょうか。 こんな記事はありますが、10倍というのは、パフォーマンスの低下が甚だしいですね。 http://www.computerworld.jp/topics/mcore/133949-1.html

_hitoshi_
質問者

お礼

回答ありがとうございます。 >例えばXPで10秒で終わる処理がVista、7では100秒かかったりするのでしょうか その通りです。 XPで20秒くらいで終わるプログラムが、Vista, 7で数分かかります。 メインスレッドが8個のサブスレッドを起動して、 全サブスレッドの終了をループで待機するプログラムです。 各サブスレッドも、USBデバイスのステータスをループで監視しています。 9スレッド全て、ループの中で次のメッセージ処理をしていますが、 これを除いても結果は変わりません。 while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ){   TranslateMessage( &msg );   DispatchMessage( &msg ); }

関連するQ&A

  • マルチスレッドについて

    現在”猫でもできる”の87、88章を学んでおります。 まず87章でマルチスレッドの根本的なやり方を学びましたが、いきなり疑問が浮かびました。 _beginthread関数によりスレッドをスタートさせ、この関数で登録した関数内で_endthread関数を実行し終了させていることは分かります。 しかし_beginthread関数で登録した関数に引数を渡す処理がどの部分で行われているのかわかりません。 登録する関数はvoid型で引数はvoid*型でなければいけないことは分かったのですが、プログラムのどこを見てもこの登録した関数に引数を渡す処理が行われていません。 その辺の動作の説明を分かる方でいいのでよろしくお願いします。 そして88章では排他制御のマルチスレッドを行うプログラムの製作を行っているのですが、ちょっとした疑問が浮かびました。 EnterCriticalSection関数、LeaveCriticalSection関数ではさまれたプログラムは排他制御され他からアクセスされない。 この関数はこんな理解で良いんですかね? この理解で行くと、88章で説明していきますが、子ウィンドウを2つ作成しそれぞれのプロシージャ内で排他制御された関数をスレッドとしてスタートしています。 この2つのスレッドの動作についてですが、互いに排他制御関数が記述されているため、動作としてはまず左の子ウィンドウのスレッドが処理されている場合、右の子ウィンドウのスレッドは停止している。そして左の子ウィンドウのスレッドの排他制御が解放されたときに、右の子ウィンドウのスレッドが開始する。 そしてあるとき左の子ウィンドウのクライアントウィンドウ内で右クリックされた場合、その時点で排他制御されたスレッドが終了するのを待ち、終了したらcountを+1する。 こんな動作が行なわれていると理解してよいのでしょうか?

  • Windows CE 5.0のマルチスレッド

    Windows CE 5.0上で動作するプログラムで、シリアルの送受信処理をUIウインドウを作成し、別スレッドとしているのですが、メインスレッド(メインダイアログ)以外のスレッドだと、動作が不安定な事が起こりえると耳にされた方はいらっしゃいませんか? 実は、不定期ではありますが、↑のプログラムを走らせていると、フリーズしてしまうという障害が発生してまして、原因が不明です。 社内の人間から、CE 5.0の動作が不安定な事があるという事を聞き、ネットで色々と調べましたが、このような報告等を見付ける事が出来ません。 シリアルの送受信を、メインスレッド内で行うように改造を検討していますが、その為の情報を収集しているところです。(上司を説得する為) どなたか聞かれたか、ネットで見かけたという方、教えて下さい。 Windows CE 5.0 開発言語:VC++2005 プロジェクトの種類:スマートデバイス プラットフォームSDK:STANDARDSDK_500 以上、よろしくお願いします。

  • マルチスレッドの動作停止について質問なんですが

    マルチスレッドの動作停止について質問なんですが 現在、C++とDirectXを使用してマルチスレッドプログラムを作成しているのですが、 どういう訳かプログラムそのものが動作停止を起こしてしまいます 状況としては 1、マルチスレッドは初期の読み込み時にのみ使用していて、毎回同じものを同じ順番で読み込んでいる。 2、読み込んでいるものは3Dモデル、2D画像の二つ 3、毎回動作を停止する訳ではなく、3~4回に1回の割合で停止する 4、動作を停止している位置を調べてみると毎回違う箇所で動作を停止している 5、スレッドセーフで作っており、デッドロック等は起こっていない 6、エラーは例外は出ない 以上の状況で、プログラムの停止する可能性のある原因について心当たりがある方がいれば教えていただきたいです

  • プログラムのマルチスレッド化について。

    マルチスレッド化したプログラムの作成を行いたいと思い、 前に作った、スライス画像を作成するプログラムを マルチスレッド化しようと、自分作ってみたのですが、デバック中に エラーで、止まってしまいます。 プログラムはこれです。http://koushi12.if.land.to/main.h この中の、///ここでエラーがでます/// というところで止まってしまいます。 ちょっと長いので、もしお時間ある方いらっしゃっいましたら見ていただき、修正箇所を指摘していただきたいのですが、 プログラム読むほど時間無い方には、質問で答えて頂きたいのですが、 各スレッドに、データ(引数)を渡すところで、 1つのデータ(例えばポインタで作ってある、画像データ)を、2つのスレッドに渡しても大丈夫なのでしょうか? データは、2つ作って、それぞれを、それぞれのスレッドに渡さないとダメなのでしょうか? それと、例えば、出力関数などを1つだけ作ってあったとして、 それを、各スレッドの中で、呼び出して大丈夫でしょうか? 関数も、各スレッドが呼び出しで衝突しないように、2つ作る必要があるのでしょうか? すみませんが、回答よろしくお願いします。

  • マルチスレッド

    ウインドウズプログラミングを始めて1ヶ月弱の初心者です。 色々探してみたのですが、結局良く分かりませんでした。 宜しくお願いします。 以下のリンクにおいて、 http://wisdom.sakura.ne.jp/system/winapi/win32/win143.html 1)主スレッドとは、具体的にソースファイルのどこからどこまでのことを言うのでしょうか? そもそもスレッドとは何でしょうか?関数のことでしょうか? また、タスクとは、実行ファイルと考えて良いのでしょうか? 2)副スレッド(ThreadFunc)を作成すると、主スレッド(WinMain?)と副スレッドで並列処理をするとのことですが、CPUは普通一つしかないので、実際は、主スレッド(WinMain?)と副スレッドを常に切り替えながら動作すると思います。が、ここで疑問なのですが、主スレッドと副スレッドの切り替えはいつ誰が行うのでしょうか?また、切り替えタイミング(例えば1ms毎に切り替えたいとか)は自由に設定出来るのでしょうか? 3)"マルチスレッドは親プロセスのメモリ空間を共有します" とあるのですが、これは CreateThread(NULL , 0 , ThreadFunc , (LPVOID)hWnd , 0 , &dwID) の(LPVOID)hWnd を、副スレッド(ThreadFunc)に引数として渡しているから、つまり、主スレッドと副スレッドは、(LPVOID)hWnd だけがメモリを共有する、ということでしょうか? 主スレッドと副スレッドでメモリを共有すると、どんなメリットがあるのでしょうか? 4)マルチスレッドはこういう時に使うとよい、 というような大まかな判断基準があれば教えて下さい。 分かり辛い質問で申し訳有りません。宜しくお願い致します。

  • MSDE2000のパフォーマンス低下

    MSDE2000のパフォーマンス低下 MSDE2000を使ったシステムがあるのですが、2,3ヶ月すると、目に見えてパフォーマンスが低下してしまいます。サービスを再起動すると、元のパーフォーマンスに戻るのですが、何か対処はあるのでしょうか?それとも、MSDE2000が開発用という事で、再起動するしかないのでしょうか? 環境 ・24時間連続稼動 ・4クライアントから読み書きしています。 ・OSは、MSDE2000がインストールされているPCも含め、5台ともWindows2000Server ・ソフトウェアの開発言語は、Visual C++6.0 こうしたら、という対処がありましたら、助言をお願いします。 以上、よろしくお願いします。

  • JDBCのパフォーマンス

    JDBCのパフォーマンスがあがらず困っています。 LinuxマシンでOracleを稼働しており、そこにJDBCで接続しています。単一でのアクセスでは全く問題のないパフォーマンスですが、同時接続数が2以上になると途端に悪くなります。 # スレッド1→スレッド10でレスポンスに5倍の時間がかかってしまう。。。 OracleでMTS設定なども行ってみましたが、変わりませんでした。コネクションプールも行っています。 JDBCを用いてマルチスレッドでアクセスするときにボトルネックとなるポイント、チェック項目等、アドバイスをいただければ助かります。 よろしくお願いいたします。 [環境] Linux RedHat6.2J(カーネル2.2.14smp) Oracle8.1.6 JDK1.3.0 JDBCドライバ Oracleで配布しているclasses12.zip

  • マルチスレッド化。

    今とても大きな配列を使用し、長時間処理をするプログラムを組んでいます。元々処理時間に1時間を要するプログラムを2分で処理を完了するまでに仕上げました。 しかし、探究心はおさまらずもう少し高速化に挑みたいと考えています。 過去に「猫でもわかる」のSDK第1章と2章を学び、マルチスレッドのプログラムをSDKで組んだことがあります。それを利用してマルチスレッド化を実現したいと考えています。 言語はCでVisualStudio2005を使用しています。 *疑問1   SDKの場合WinMain関数とプロシージャからの実行で_beginthread関数を記述すれば処理が開始されます。 Cでもmain関数内に記述すれば、SDKと同様に処理できるのでしょうか? *疑問2 _beginthread関数の引数に関してです。 第1引数にvoid型のスレッド関数、第2引数に0?、そして第3引数にはスレッド関数に渡すデータの引数を記述すると把握しているのですが、渡したいデータは複数あり、***型と**型、それに変数を数個とスレッド関数に渡したいデータだらけなのですが、どのように記述すればよいでしょう? *疑問3 2つのスレッドを作成しようと考えていますが、その2つのスレッドで1つの大きな配列を共有して処理したいと考えています。 そのため、スレッド間の同期が必要になるわけですが同期の種類にもクリティカルセクションやミューテックス、イベントと豊富でどれを使用すれば良いのか迷ってしまいます。厳密に同期を取り処理をするにはイベントが一番良いと考えています。 これらの疑問に答えられる方はアドバイスをよろしくお願いします。

  • マルチスレッドに挑戦したい

    <プログラム環境> Windows XP VC++6.0 MFC AppWizard(exe) ダイアログベース <目的> COMポートでバイナリデータの送受信を行う <プログラムの仕様> 1.ダイアログの「受信開始」ボタンを押す    データ受信開始の合図"0x01"を相手機器に送る 2.相手機器がデータを永遠と送信してくる 3.データを永遠と受信する 4.ダイアログの「受信終了」ボタンを押す    データ受信終了の合図"0x02"を相手機器に送る 5.相手機器がデータ送信を止める 6.受信終了 <質問> 上記のプログラム仕様を満たすには、マルチスレッドにしないといけないと思うのですが(データの送信と受信でスレッドを分ける)、具体的に何をどうすればマルチスレッドになるのか分かりません。 マルチスレッドに必要な関数、 プログラムの全体的な流れなど、 基本的な部分を教えてください。 宜しくお願いします。

  • マルチスレッドでブレイクポイントするとフリーズする

    C++/CLI .Net2008 windowsフォームアプリケーション 二つのスレッドが同時に動いているマルチスレッドプログラムを作成しています。 デバッグでブレイクポイントを張って途中で止めたいのですが、止めてすぐもしくはF10で2,3行進めるとフリーズしてアプリが動かなくなってしまいます。他のoutlook等も動かせず、タスクマネージャも開かないため、画面下のウィンドウを右クリック、閉じるを5~10分くらいかけて行って終了させています。たまにVisualStudio自体もフリーズして落ちることがあります。 ブレイクポイントで止めなければフリーズはしません。 プログラムの構成としては、 片方は外部装置からリアルタイムでデータを受信し、判別した結果を出力するスレッドと、その判別結果を元に状態を遷移させるスレッドです。 また、状態によってはタイマーを設けている箇所があり、タイマー処理もスレッドで行っています。 ブレイク張らずに実行した時におかしい動作をしている箇所があるので1行ずつ見たいのですが、マルチスレッド環境ではフリーズするものなのでしょうか?