いつもお世話になっております。
今回はマルチスレッドプログラムについてお聞きしたいです。
マルチコアCPUを使ってたとえば下記のようなことをしたいときに
for (int i = 0; i < 1000000; i++)
{
sum += i;
}
このまま計算するよりもいくつかスレッドを作って、計算量を分散させてから最後に足してやるほうが早いと思いまして、
現在Core2Quadが手元にありましたのでスレッドを4つ作って
スレッド1で0から250000まで
スレッド2で250001から500000まで
スレッド3と4も同様にして実際にやってみたのですが
スレッドなしの状態よりも倍くらい時間がかかってしまうようになってしまいました。
計算結果は同じになり、CPU使用率もシングル時が25%、マルチ時が100%になっているので意図したようにはできていると思います。
GetProcessAffinityMaskを使って、各スレッドにひとつづつコアを割り当てても同様でした。
実際に時間が4分の1に近くなると思っていたのですが2倍かかってしまったので不思議です。
どなたか上記のことを思惑通りに動かせそうな方法をご存知の方はご教授願います。
プログラムは全部は無理ですが重要そうなところは下記のとおりです。
スレッド作成部分
{
DWORD dwStart = ::timeGetTime();
_thread_handle[0] = (HANDLE)::_beginthreadex(NULL, 0, thread_first, NULL, CREATE_SUSPENDED, &_thread_first_id);
_thread_handle[1] = (HANDLE)::_beginthreadex(NULL, 0, thread_second, NULL, CREATE_SUSPENDED, &_thread_second_id);
_thread_handle[2] = (HANDLE)::_beginthreadex(NULL, 0, thread_third, NULL, CREATE_SUSPENDED, &_thread_third_id);
_thread_handle[3] = (HANDLE)::_beginthreadex(NULL, 0, thread_forth, NULL, CREATE_SUSPENDED, &_thread_forth_id);
for (int num = 0; num < 4; num++)
{
::ResumeThread(_thread_handle[num]);
}
::WaitForMultipleObjects(4, _thread_handle, TRUE, INFINITE);
for (num = 0; num < 4; num++)
{
::CloseHandle(_thread_handle[num]);
}
DWORD dwEnd = ::timeGetTime();
}
各スレッド部分
{
HANDLE hCurrent = ::GetCurrentProcess();
DWORD pamask, samask, patmp = 0;
int nRet = ::SetProcessAffinityMask(hCurrent, 0x0001);
::GetProcessAffinityMask(hCurrent, &pamask, &samask);
DWORD dwStart = ::timeGetTime();
_result1 = 0;
for (int multi = 0; multi < _multi; multi++)
{
for (DWORD i = 0; i < 100000/4; i++)
{
_result1 += i;
}
}
DWORD dwEnd = ::timeGetTime();
time1 = dwEnd - dwStart;
::_endthread();
return 0;
}
開発環境は
WindowsXP SP3
VisualStudio6.0 ATL/WTLです。
A 回答 (7件)
- 最新から表示
- 回答順に表示
No.7
- 回答日時:
もうすでに解決されてると思いますが、おそらくこうではないでしょうか?
× SetProcessAffinityMask
○ SetThreadAffinityMask
No.5
- 回答日時:
省略した箇所に原因が潜んでいることが多いので、実検証できるソースを提示しないとなかなか解決には至らないと思います。
以下気になったこと。
(1) シングルスレッドのソースと比べ、マルチスレッドの処理で以下のfor文が追加されていますがなんでしょう。
for (int multi = 0; multi < _multi; multi++)
(2) _beginthreadex で開始したら、終了は _endthreadex です。
(3) CriticalSection, Mutex など排他制御はやってませんか ?
この回答への補足
補足です
(1)足し算を行う回数です。何回足すかを指定できるようにしています。
転載のとき削り忘れました。
(2)修正しましたが変化なしでした。
(3)排他はしておりません。4つの和を最後に足して、シングルのときの結果と比較しております。
No.4
- 回答日時:
スレッド生成とか同期のコストに比べて演算負荷が軽すぎるのでは?
もう一桁二桁上げてどうなるか見てはどうでしょう。
この回答への補足
ご回答ありがとうございます。
もう一桁二桁というか、足すfor文の回数を1回から16回繰り返しまでできるようになっているのですが、妥当に回数倍かかってしまいました。
No.3
- 回答日時:
私の処理では、並列にするとスピードアップしました。
始め、関数として普通に呼び出します。
その次、ワーカスレッドへポインタを渡し、上記関数を実行しました。
すると俄然スピードが上がりました。
ただ、その調子で32個もスレッドを組んだお陰で、やたら不安定なプログラムになりました。
まぁ、今回は勉強だと思って、作り直したらと言われています。
スレッドは、作って見ないと解らないところがあります。やりすぎると、大変な目にあいます。ご注意ください。
ページフォールトは少なくなるようにしたほうがいいですよ。
(タスクマネージャでモニター可能)
No.2
- 回答日時:
推測の域を出ませんが、以下のような理由では?
整数の単純加算のように、待機の全く発生しない処理ではマルチ
スレッドによる恩恵は殆どありません。むしろ、制御のための
オーバーヘッドが原因になっているのではないでしょうか。
ファイル入出力や通信など、自CPU以外の相手がある場合、相手の
動作完了までWaitがかかります(つまり、待機がある)。この
待ち時間を利用して、別の処理をするという時には恩恵があります。
大容量のファイルのコピーなどを題材にして実験してみてください。
No.1
- 回答日時:
間違っているかもしれませんが ・・・
制限のかけ方を間違っているのではないでしょうか
4コアならば
1番目のスレッドは
::SetProcessAffinityMask(hCurrent, 0x0001);
2番目のスレッドは
::SetProcessAffinityMask(hCurrent, 0x0002);
3番目のスレッドは
::SetProcessAffinityMask(hCurrent, 0x0004);
4番目のスレッドは
::SetProcessAffinityMask(hCurrent, 0x0008);
といった具合にすればコアごとに処理すると思います
すべてのスレッドで
::SetProcessAffinityMask(hCurrent, 0x0001);
としてしまうと 1番のコアのみで処理するのではないでしょうか
当方のCore2Duoですと
::SetProcessAffinityMask(hCurrent, 0x0001);
の場合コア1のみしか使われないようです
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- C言語・C++・C# バイナリファイルをコピーするのにかかる時間を測りたいのですが実行するとFatel error:gli 2 2022/11/03 01:10
- MySQL my_itemsテーブルのIDにAUTO_INCREMENT を追加ができるかで 1 2023/01/03 09:09
- C言語・C++・C# C言語プログラム変更 2 2022/12/21 15:03
- C言語・C++・C# 質問です 下記のコードを分かりやすく解説お願いします 初心者です #include ‹stdio.h 3 2022/05/26 22:03
- PHP php テーブルが作成できない 1 2022/11/17 23:41
- MySQL `picture` varchar(255) のコマンドで間違いないでしょうか? 1 2022/11/21 04:08
- MySQL php テーブルを作れない 2 2022/11/17 18:22
- C言語・C++・C# C言語でif文が予想と違う動きをする件について7 4 2023/03/20 00:26
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
VC++スレッドの正しい終了のさ...
-
マルチスレッド?
-
C# スレッド終了の監視について
-
スレッドの監視方法について
-
WaitForSingleObjectの使い方に...
-
マルチスレッドプログラミング...
-
スレッドの終了はどうやるんで...
-
スレッドの安全な終了のさせ方
-
VC++ Workerスレッドを強制終了...
-
Linuxでスレッド優先度って変え...
-
VB2005 シリアル通信のClose処理
-
.netアプリへのSendMessageでフ...
-
Macターミナルで実行中のプログ...
-
緯度、経度の 10進法と 60進法...
-
Windows10でDOSゲーム
-
explorer.exeが異様にメモリを食う
-
自分自身を更新するプログラム
-
TCP/IP通信時のサーバーからの受信
-
C言語で、メモリを解放しないで...
-
他のEXEが起動しているかの確認
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
WaitForSingleObjectの使い方に...
-
VC++スレッドの正しい終了のさ...
-
スレッドの監視方法について
-
スレッドの安全な終了のさせ方
-
スレッドにて同一メモリの書き...
-
Windows上で、シグナル(SIGTERM...
-
スレッドの終了の仕方
-
スレッドの終了はどうやるんで...
-
VB2005 シリアル通信のClose処理
-
マルチスレッドプログラミング...
-
.netアプリへのSendMessageでフ...
-
マルチスレッドについて
-
Linuxでスレッド優先度って変え...
-
Win32APIでのスレッド処理
-
pthread_cond_wait 取りこぼし?
-
LinuxでDoEvents()同等機能
-
C++ GUIのメッセージループ。
-
excelvbaでCreateThreadの動作
-
マルチスレッドの実行順序の制御
-
同一スレッドで、ロックをかけ...
おすすめ情報