マルチスレッドプログラミング相談室 その5at TECH
マルチスレッドプログラミング相談室 その5 - 暇つぶし2ch2:デフォルトの名無しさん
06/09/10 00:19:06
関連スレ

【マルチコア】並列化について語る【使いこなせ】
スレリンク(tech板)

pthread地獄 (UNIX板)
スレリンク(unix板)


関連しやすいので一応

ネットワークプログラミング相談室 Port17
スレリンク(tech板)l50

書籍とかはもういいでしょ

3:デフォルトの名無しさん
06/09/10 00:33:25


4:デフォルトの名無しさん
06/09/10 15:04:22
4ね

5:デフォルトの名無しさん
06/09/10 16:03:40
5免蒙る

6:デフォルトの名無しさん
06/09/11 07:05:53
pthreadで排他制御やりたいときはmutexしか選択肢は無いんでしょうか?

7:デフォルトの名無しさん
06/09/11 22:08:46
condition,semaphore

8:デフォルトの名無しさん
06/09/18 01:43:12
本とかはもういいとして、このソースのthread部分は秀逸だっていうの
教えてください

9:デフォルトの名無しさん
06/09/18 09:25:39
apache2(ウソ)

10:デフォルトの名無しさん
06/09/18 10:05:22
Windowsのスレッドのタイムスライスは、上限が20msと聞きますが
これを制限する方法はありませんか?
できれば、3~5msに押さえたいのです。

11:デフォルトの名無しさん
06/09/18 16:44:32
NT4.0を使って、boot.iniで設定。
Windows Embeddedならどっかで設定できたような。
Vistaは割り込み頻度を変えるAPIがあったかもしれず。

12:デフォルトの名無しさん
06/09/18 20:34:42
Fiber使ってで明示的にスイッチするとか

13:デフォルトの名無しさん
06/09/18 21:47:30
>>11
ありがとうございます。
こちらでも調べてみたのですが
win9x/2000でのスレッド単位での設定は出来ないようですね。
スレッドスケジューラを少しいじれば、可変に出来る気がするのですが
あんまり需要無いんですかね。

>>12
ファイバを使ってsuspendを置くか、スレッド関数にSleepを置くか、
結局のところ、これしかしかないのですね……
どちらか採用して、今のプロジェクトを進めようと思います。

14:デフォルトの名無しさん
06/09/19 10:53:29
>>10

たしか、どっかにVistaのタイムスライスに関する blogがあったな。
××をすると、スイッチが最小時間になると適らないとか。

どっかの、MVPの blogだったと思う。


15:デフォルトの名無しさん
06/09/19 21:01:54
>>14
Vista+タイムスライスでググってみた。
URLリンク(d.hatena.ne.jp)
ついでに
URLリンク(www.itmedia.co.jp)

16:デフォルトの名無しさん
06/09/21 21:28:56
InsideWindowsには
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\PriorityControl]
のWin32PrioritySeparation
をいじればいいと書いてある


17:デフォルトの名無しさん
06/09/21 22:55:26
ってスレッド単位で制御したいのか

そりゃ無理っぽいな

18:デフォルトの名無しさん
06/10/07 12:26:02


19:デフォルトの名無しさん
06/10/10 14:57:19
>>14
kernel修正すればいいじゃん。
2.6.xなら安定してるしNPTLを使えばOKだし

20:デフォルトの名無しさん
06/10/10 21:20:44
?

21:デフォルトの名無しさん
06/10/26 16:02:30
マルチプロセスのプログラムはWindowsで作れますか?

22:デフォルトの名無しさん
06/10/26 17:21:43
>>21が意図してるものとは異なるかもしれんが、マルチプロセスのアプリケーションなら作れる。
しかし>>21の質問の仕方からして、>>21には到底無理だろう。

23:デフォルトの名無しさん
06/11/04 17:13:38
質問させてください。
Win32APIのSuspendThread()に自スレッドを指定して、
自分自身を眠らせるということは可能でしょうか?

24:デフォルトの名無しさん
06/11/04 18:06:36
試せばいいじゃん

25:デフォルトの名無しさん
06/11/04 18:47:40
どうやって起こすの?
イベントオブジェクト作ってWaitForしたほうがマシだと思うが・・・

26:デフォルトの名無しさん
06/11/04 19:11:44
>>24
すいません、「可能」は「アリ」に置き換えてくださいorz
一応動くんですが、何かマズイんじゃないかなぁと思いまして。

>>25
仰るとおり実用的ではないですが、ちょっと気になったもので…

27:デフォルトの名無しさん
06/11/06 15:24:05
>>23
他スレッドからResumeThreadしようとしたとき、Resumeしても SuspendThread の直前だったため
Resume後即 Suspend してしまうケースがある。 → 解決するためには「スレッドのステート(idle,busyなど)」を設けて、
排他的に操作する必要あり。適切なイベントオブジェクトを使って待つ方が良い。

それでもまぁ他のスレッドを Suspend するのに比べればはるかに罪は少ない。

28:デフォルトの名無しさん
06/11/07 09:09:31
408 :名無しさん@お腹いっぱい。:2006/11/05(日) 18:14:14
Kentsfield(1P4C) vs Woodcrest(2P4C)
URLリンク(www.hardwarezone.com)
Opteronサーバー死んだな…
Clovertown 1.60GHz $455*2 >>> Opteron 2220 SE $786*2
Clovertown 2.33GHz $851*2 >>> Opteron 8220 SE $2149*4

29:デフォルトの名無しさん
06/11/09 22:08:24
967 名前:923[sage] 投稿日:2006/09/09(土) 17:29:41
>>959
>intrinsicはスルーか。
済みません、仰りたいことの意味が良く分りませんでした。
このプログラムの要点は、

volatile long a = 0x00001111;
void thread1(){
 while(1)a=0x00001111;
}
void thread2(){
 while(1)a=0x22220000;
}
int main(){
_beginthread(thread1);
_beginthread(thread2);
 while(1)if(a != 0x00001111 && a != 0x22220000)エラー;

return 0;
}

です。組み込み命令云々の余地があるのでしょうか?

main, thread1, thread2が開始される。
~~~時間が十分経過~~~
thread2が動き出す。a=0x22220000が実行される。
mainが動き出す。a!=0x00001111の評価をする。真であった。
thread1が動き出す。a=0x00001111が実行される。
mainが動き出す。a!=22220000の評価をする。真であった。
mainが動き出す。エラー処理を行う・・・???。

30:デフォルトの名無しさん
06/11/10 02:13:19
複数のスレッドを起動する場合、
システムに異常が発生しても全てのスレッドを
必ずきちんと終了させたい場合、各スレッドで try catch
入れるんでしょうか?
それとも別に良い常套手段があるんでしょうか?


31:デフォルトの名無しさん
06/11/10 06:01:09
システムに異常が発生した事を検知する関数が真を返したらすべてのスレッドが自主的に終了するようにしたらいいんちゃうん?

32:デフォルトの名無しさん
06/11/10 08:53:37
ええんちゃう? 最高ちゃう?

33:デフォルトの名無しさん
06/11/10 09:56:27
volatile最強伝説復活wwwwwwwwwwwwwww

34:デフォルトの名無しさん
06/11/10 19:04:31
このスレも自主的に終了するようにしたらいいんちゃうん?

35:デフォルトの名無しさん
06/11/10 20:51:25
ええんちゃう? 最高ちゃう?

36:デフォルトの名無しさん
06/11/10 23:12:02
>>29

while(1)if(a != 0x00001111 && a != 0x22220000)エラー;
を分解して
while ( true )
{
if ( a != 0x00001111 ) // a is 0x22220000
{
if ( a != 0x22220000 ) // a is 0x00001111
{
throw std::runtime_error("死んでしまえ");
}
}
}


37:デフォルトの名無しさん
06/11/17 16:54:00
>>36
こうすりゃいいんじゃね?

while(1){
int _a = a;
if(_a != 0x00001111 && _a != 0x22220000)エラー;
}

要は00001111か22220000以外が見つかればエラーにしたいんだから。
>>29指摘のコンテキストスイッチによる嘘エラー検出は回避できる。


38:デフォルトの名無しさん
06/11/19 14:18:42
初心者です。
スレッドの状態(実行中・サスペンド中など)を知るAPIってありますか?

State = ResumeThread( th_handle ) 又は
State = SuspendThread( th_handle )
として サスペンドカウントを見て状態を更新させています。
状態を監視する別スレッドがこのStateを見て、レジューム・サスペンドの実行をおこなっているのですが、

どーやら、状態を監視するスレッドが見ているStateと実際の状態が異なるらしく、
レジューム中のスレッドにResumeThread を実行したり、サスペンド中のスレッドにSuspendThread を実行しちゃったりしています。

なにかアドバイスもらえませんか?
おねがいします。

OS : Window XP Home
言語: C++
環境: VC++6.0

39:デフォルトの名無しさん
06/11/19 14:24:04
resume/suspendよりも、event objectやwindow messageを使って
眠らせることをオススメするよ。

40:38
06/11/19 14:35:34
>>39

アドバイス、ありがとうございます。
イベント使って、再設計してみます。

それと、色々さがしたんすけど、やっぱりスレッド状態を知るAPIとかは
ないんすかね?





41:デフォルトの名無しさん
06/11/19 14:39:09
知ったところでどうしょうもない、とだけ言っておこう。
だからないのよ。

42:38
06/11/19 14:45:36
>>41
了解です。ありがとうございます。

助かります~

43:デフォルトの名無しさん
06/11/19 17:51:29
>>40
状態を調べたところでその次のステップで状態が変わってる可能性もあるわけで、
結局、排他やロックなどが必要になるわけです。
だったらはじめから>>39の方法の方が妥当なのです。

44:38
06/11/19 23:36:56
38です。
イベント使って再設計したとこ、なんとか思い通りに動いてくれました。
みなさん、どうもありがとう。
いい勉強になりました~

45:デフォルトの名無しさん
06/11/20 16:10:26
linux上のC言語での質問です。

pthread_create を使ってスレッドを生成すると、そのスレッドが完了しても
1個スレッドが残るんですが、これって開放出来ないんですか?

デバッガで調べると「pthread_managear」というスレッドのようなのですが。


46:デフォルトの名無しさん
06/11/20 20:40:45
>>45
スレッドマネージャもためらいきずばかりなんだよね
自殺はよくない

47:デフォルトの名無しさん
06/11/21 01:19:01
どのlinux?
それなくなったとか聞いたんだが

48:デフォルトの名無しさん
06/11/21 09:28:07
>47
Red Hat Linux 7.3 です。

49:デフォルトの名無しさん
06/11/21 19:20:58
pthread_joinしてないとかそういう話じゃないの?

50:デフォルトの名無しさん
06/11/22 13:33:05
>49
joinはしてます。
あと 、pthread_detach も試して見ましたが変わらずでした。

51:デフォルトの名無しさん
06/11/23 14:14:40
windows c言語です。
_beginthreadexでスレッドを数千つくろうとしてるのですが、
スレッド数400ぐらいこえたところで、_beginthreadが0を返しだすので仕方なくsleepいりのbusyloop
で待って_beginthreadしつづけています。
スレッド数をタスクマネージャでながめると400になり、だんだんへって10桁程度になってから
また400に跳ね上がるのくりかえしをして、正常に終了します。が遅いです。
だんだん減っているときにはすぐに次の_beginthreadが成功してくれて、
なぜ、400のままずっといき、最後がだんだん減っておわらないのかわからないです。
あと、なぜ400で限界になるのでしょうか?
ちなみにスタックサイズをでかくするとスレッド数の限界はもっと減ります。
メモリがどんどんくわれていってスレッドももっとたくさんできて欲しいのですが・・・
スレッドの内容はメモリを動的確保しhtmlをネットから拾ってきて読むものです。

これだけでわかる人 ヒントください。

52:デフォルトの名無しさん
06/11/23 14:19:52
>>51
URLリンク(www.biccamera.com)

53:デフォルトの名無しさん
06/11/23 15:12:17
>>52
え それはないと思う。
プロセスの使用メモリ35MBぐらいなんです。
全部で1Gつんでるのに。

54:デフォルトの名無しさん
06/11/23 15:25:10
スタックメモリサイズの制限でしょ

55:デフォルトの名無しさん
06/11/23 16:03:20
> スレッドの内容はメモリを動的確保しhtmlをネットから拾ってきて読むものです。

ジョブキューイングとかワーカスレッドとか知らんかね?

56:デフォルトの名無しさん
06/11/23 17:00:57
1プロセスにスレッド400個ってのは設計上どうなんだろ…。
タスクマネージャ見ても最高でSystemの78個程度だ。


57:デフォルトの名無しさん
06/11/23 21:32:18
>>56
同意。

スレッドの生成と、管理にはそれなりのコストがかかるから、
むやみに増やしてもかえって遅くなる。

せいぜい数個から10数個くらいにとどめておくべきと思う。


58:デフォルトの名無しさん
06/11/23 22:29:39
数千スレッド使いたいってあほか。


59:デフォルトの名無しさん
06/11/23 23:13:58
PCの玄海に挑戦したかっただけだろうよきっと

60:デフォルトの名無しさん
06/11/24 01:00:08
どうもスレッドからみでは、本当に同時平行に処理したいことと、
そうでないことの区別ができてないことが多いようだ。


61:デフォルトの名無しさん
06/11/24 01:07:32
この場合は
・ネットへのリクエスト
・得られた情報の分析
が並行処理対象になると思うんだが、
前者と後者ではやりかたがぜんぜん違うよなあ

62:デフォルトの名無しさん
06/11/24 01:45:14
あまりのスケールのでかさに、別件でスレッドを使おうか迷っているのが
バカらしくなってきた

63:デフォルトの名無しさん
06/11/24 02:08:29
うちだと_beginthread()しまくるだけの奴で
スレッド2000個ちょっとまで作れるな

64:デフォルトの名無しさん
06/11/24 14:14:52
ふと>51の質問みて思ったんですが、スレッドを分ける(並列にする)
と処理速度って上がるんでしょうか。

処理の内容によるでしょうけど、単純にCPU性能に依存するような
処理で、並列に処理可能な場合とか。


まあ普通そういう目的でマルチスレッドを利用したりするわけじゃないですが。

65:デフォルトの名無しさん
06/11/24 14:15:53
ふと>51の質問みて思ったんですが、スレッドを分ける(並列にする)
と処理速度って上がるんでしょうか。

処理の内容によるでしょうけど、単純にCPU性能に依存するような
処理で、直列に処理してたけど並列に処理可能な場合とか。


まあ普通そういう目的でマルチスレッドを利用したりするわけじゃないですが。

66:デフォルトの名無しさん
06/11/24 14:16:56
連書きスマソ;

67:デフォルトの名無しさん
06/11/24 15:08:49
>>64
動作中スレッド数よりもCPUコア数が多いなら、スレッドを並列化することで高速化する。
仮に1Core1CPUで単純に並列化した場合、全く高速化しないかオーバーヘッドの分遅くなる。
まぁ、CPUコア数の数倍以上のスレッドを起こすと資源の競合が発生するから速くなる筈がない罠。

68:デフォルトの名無しさん
06/11/24 16:02:59
>>67
CPUに限らず、資源が競合する処理なら、確かにそうなるな。

逆に言えば資源を競合しないI/Oウェイトなどが多い処理なら、
CPU数より極端に多いスレッド数でも処理は早くなるといえる。

たとえば今回のようなhtmlファイルのダウンロードの場合、
相手方のサーバーのレスポンス待ちが発生するので、複数のスレッドで別々の
htmlファイルを同時に取得しにいったほうがいい。

ただ、やりすぎると今度はスレッド切り替えとか、メモリスワップとか、回線速度の限界とかで
オーバーヘッドが大きくなるので遅くなる。


69:デフォルトの名無しさん
06/11/24 16:05:55
tcpip.sysの同時接続制限とか関係ないのかな?

70:デフォルトの名無しさん
06/11/24 18:03:54
>67 68
サンクス!
実はウチの作ってるアプリで性能を指摘されてるトコがあって、
並列化ってどうなんだろうと思ったんで、参考になりました。

とりあえずCPU依存の処理は効果薄って事ですね。

71:デフォルトの名無しさん
06/11/24 19:12:42
>>70
並列化を考える前に、やることは色々あると思うよ。
CPUに、P4以上の制限つけていいならiccでコンパイルしてみるとか。
iccがあれば、並列化も簡単に試せるしね。
まぁ、詳細はスレ違いになるんで省略するけど。

72:デフォルトの名無しさん
06/11/25 01:58:51
CPU依存の処理で高速化を考えるなら、並列化ではなくアルゴリズムの最適化を考えたほうがいい。

スパコンでもない限り、今のパソコンはせいぜい4コア。
並列処理させても、4倍未満にしかならない。

だけどうまくアルゴリズムを工夫すれば、数倍から数百倍の速度が稼げる可能性がある。


73:デフォルトの名無しさん
06/11/25 02:07:56
DELLの6万円パソコン買ったほうがよくね?
10台でも60万。さてアナタの2人月より安い?高い?

74:デフォルトの名無しさん
06/11/25 02:08:38
無限に並列化可能な処理と仮定するなら、クラスタリングもありかと。
所謂グリッドコンピューティング。

75:デフォルトの名無しさん
06/11/25 02:12:36
あと2倍になればいいだけなのにチューニングだとかほざいて
無駄にコードを複雑にしようとしていたボケがいたので
サーバを3倍に増やして終わりにしました。

76:デフォルトの名無しさん
06/11/25 02:53:01
ま、そこら辺は完全にケースバイケースだよね。お仕事でやってるならコスト次第。
このスレ的には並列度を上げる方向に収束すると美しいんだけど。

77:デフォルトの名無しさん
06/11/25 03:05:17
そんな勝手に方向を決められても。

78:デフォルトの名無しさん
06/11/25 12:57:34
>>71
>iccがあれば、並列化も簡単に試せるしね。
体感で速くなったためしがない。

いったいどういう場合に効果があるのか…。

人間が見ればすぐ分かるが、コンパイラの並列可能判定って
どの程度のものなんだろう。

79:デフォルトの名無しさん
06/11/25 12:58:54
↑もちろん手動で並列化したら高速化できる状況での話ね。

80:デフォルトの名無しさん
06/11/25 13:11:18
>>78
勿論、最低限-parallelは指定しているとして、単純なループなら並列化してくれる可能性はあるよ。
尤も、OpenMPを手軽に試せるという積もりで書いたんだけど。

81:デフォルトの名無しさん
06/11/30 20:10:54
Sunコンパイラ最強伝説

82:デフォルトの名無しさん
06/12/02 20:35:28
最近、コンパイラの最適化性能比較ってあんま情報ないな。


83:デフォルトの名無しさん
06/12/03 21:51:02
すいません、マルチスレッドですか?

84:デフォルトの名無しさん
06/12/03 22:42:46
はい、マルチスレッドです。

85:デフォルトの名無しさん
06/12/03 23:28:53
あなたを、マルチスレッドです。

86:デフォルトの名無しさん
06/12/06 23:09:42
今日は徹夜でpthreadを勉強します。

87:デフォルトの名無しさん
06/12/07 01:09:39
こんやは徹夜で、マルチスレッドです。


88:デフォルトの名無しさん
06/12/07 11:08:50
それはいいマルチスレッドですね。

89:デフォルトの名無しさん
06/12/07 22:25:54
俺はみんながマルチスレッドしたあとでいいよ

90:デフォルトの名無しさん
06/12/07 22:29:26
みんないっしょでこそマルチスレッドです

91:デフォルトの名無しさん
06/12/07 23:01:07
俺ちょっと疲れたからみんな先にいってくれ

92:デフォルトの名無しさん
06/12/08 03:40:09
急激にスレの質が落ちて参りました

93:デフォルトの名無しさん
06/12/08 14:50:27
みんなでマルチコスレッドしねぇ?

94:デフォルトの名無しさん
06/12/08 21:05:24
JavaScriptの分際でマルチスレッドしてやがる事に最近気付いた。
仕組みどうなってんのよ?

95:デフォルトの名無しさん
06/12/08 21:57:49
Javascriptなら中身見れるでしょーが

96:デフォルトの名無しさん
06/12/08 22:03:46
ソースの問題じゃなくてCPUがどう処理をこなしているか知りたいんだよな

97:デフォルトの名無しさん
06/12/09 00:36:36
並行動作はせんと思うが

98:デフォルトの名無しさん
06/12/09 00:59:15
CPU?

99:デフォルトの名無しさん
06/12/09 01:01:50
onBlurとonClickで並列処理するよ。

100:デフォルトの名無しさん
06/12/09 01:02:26
だめだこりゃ

101:デフォルトの名無しさん
06/12/09 01:14:01
<script>
function Test(){
while(1){}
}
</script>

...
<span onclick="Test()">Hello World!</span>


でブラウザ死ぬけど?

102:デフォルトの名無しさん
06/12/09 01:18:19


103:デフォルトの名無しさん
06/12/09 01:28:07
どのブラウザで?
つかブラウザネタをここでやるのか・・・ヤだなあ

104:デフォルトの名無しさん
06/12/09 04:50:27
ここはやっぱり伝家の宝刀 volatileネタを持ち出して本来のスレの荒れ方に戻そうよ。

105:デフォルトの名無しさん
06/12/11 10:38:50
Intel C++ Compiler for LinuxでOpenMPを使った並列化をやっているのですが、Intel Thread ProfilerにはLinux版が存在しないので、
暗黙的/明示的なバリア, ループの分割, critical構文等のオーバーヘッドや負荷の不均衡が検出出来ず、いまいちパフォーマンスが伸び悩んでおります。
このような問題を解決できるLinux用のツールは存在するのでしょうか?
それともWindowsに移行するという選択肢しかないのでしょうか?
なんだかレベルの低い質問で慙愧に堪えないのですが、もし誘導や解答をいただければ嬉しいです。

Intel Thread Profiler
URLリンク(www.intel.com)

106:デフォルトの名無しさん
06/12/11 18:47:00
一昔前だったらまともなスレッドプログラミングしたけりゃSolaris使え、で
片付けられてたような気がするけど私も興味あるので識者の降臨を待つ。
Valgrind(Helgrinid)の他にLinuxで実用に耐えるツールはあるのかな、と。

107:デフォルトの名無しさん
06/12/11 19:06:34
とりあえず脳味噌ぶら~んから適当に検索。
URLリンク(www.nbrains.net)
URLリンク(www.nbrains.net)

108:105
06/12/11 22:40:37
>>106-107
御解答有難う御座います。
わざわざ検索していただいたのに申し訳ないのですが、ちょっとその中には無いようですorz
凹んでいるだけでは何にもならないので、とりあえず"OpenMP"でググって片っ端から有望そうな所を覗いてみました。
結果、Omni OpenMP Compilerにtlogviewなるツールがあることがわかりました。
URLリンク(phase.hpcc.jp)
これを使えば、「iccでOpenMPを使った限界までのパフォーマンスチューニング」は難しそうですが、
「自分のコードの駄目なところ(計算粒度、ロードバランス等)を効率的に見つける」ことはできそうな感じです。
これを使って駄目だったらWinへの移行も検討してみようと思います。

109:デフォルトの名無しさん
06/12/11 22:42:55
SolarisがN:Mスレッドモデルをやめたのは効率が悪かったから?

110:デフォルトの名無しさん
06/12/11 23:45:55
アプリが1:1モデルを前提に作られる(チューンされる)ようになったから。
アプリといってもぶっちゃけoracleだが。
SolarisのためだけにN:M用チューンするのは時間の無駄だからね。

これを効率というならば効率だね。

111:デフォルトの名無しさん
06/12/20 09:58:49
I/.O主体の仕事は前提とかチューンってこととは関係なく、
1:1の方が効率がいい場合が多いでしょ。
CPUを明け渡すのがカーネル内であることが多いから。
だからエンタープライズが主戦場のSolarisでは当然のことかと。

112:デフォルトの名無しさん
06/12/20 10:23:41
OSが1:1ばかりになったというのもあるよ

113:デフォルトの名無しさん
06/12/21 01:18:13
 そういうことは関係ない。
ちゃんと選んでやっている。

114:デフォルトの名無しさん
06/12/21 01:28:43
M:Nはシグナルの動きが1:1のときと全く同じにはならない。
両モードでのデバッグや検証コストを掛けられない。

もう一つは>>112のとおり。
OS屋のオナニーで仕様が決まる時代は終わった。

115:デフォルトの名無しさん
06/12/22 22:55:26
マルチスレッドのデバッグではまっています
(私が作ったんじゃないのですが)
beginthreadが50個、EnterCriticaSectionが40個くらい、
スレッド最大200個くらいが動くとんでもないシステムです。
(もちろん満足に動いてないです)

とりあえず、下記の方針でソースをチェックしようと思いますが、
他にもありますでしょうか?

1 InitializeCriticalSection()以前の行に、_beginthreadを呼び出す関数に入ってないか
2 スタティック変数、グローバル変数にEnterCriticalSecitonなしで書き込みを
行ってないか
3 newで作ったオブジェクトのポインタを複数のスレッドで参照してないか

116:デフォルトの名無しさん
06/12/22 23:13:58
>>115
問題を正しく特定できてるのか?

117:デフォルトの名無しさん
06/12/23 00:10:24
>>116
とにかくアクセス違反で落ちたり、
const変数が書き換わったりするみたいです

もちろんマルチスレッドが原因かは特定できないのですが、
(ただ、ソースを見ると明らかにマルチスレッドを扱いきれてないです)
今、メモリ周りとかいろんな方面から数人で見ています。
もちろんデバッガ使ったりログ吐いたりはしています。



118:デフォルトの名無しさん
06/12/23 01:17:19
>>115

あと、EnterCriticalSectionへの再帰がないか。
同一スレッドだと、EnterCriticalSectionの挙動が変わるから注意。


119:デフォルトの名無しさん
06/12/23 03:03:16
どれくらいのスパゲッティ度かにもよるけども
仮想的なdbを用意して、データへのアクセスは必ずdb経由にするのも手だぞ。
(ポインタは渡さない、必ず生データのやり取りにする)
少なくとも知らない間に書き換わることはなくなる。
パフォーマンスは落ちるけどな。

120:デフォルトの名無しさん
06/12/23 09:02:59
>>118

なるほど、それは知りませんでした。ありがトン!!!!!

>>119

うーん、なるほど。それも覚えておきます。ありがトン!!!
とりあえず、ある程度安定してきたら、
再設計など検討するらしいです。

121:デフォルトの名無しさん
06/12/31 12:29:32
winapiでいうところのCrateEvent(), WatiForSingleObject(), SetEvent(), ResetEvent()
に該当する関数ってPOSIXでいうとどんなものになるんでしょうか?

mutexは双方にあって別にいいんですが、待機オブジェクトがなくて困っています。

122:デフォルトの名無しさん
06/12/31 13:24:29
>>121 condition

123:デフォルトの名無しさん
07/01/04 21:52:54
新年明けましておめでとうございます。
本年も、マルチスレッドプログラミング相談室 その5にご健勝あれ。

124:デフォルトの名無しさん
07/01/06 21:53:22
本年の相談は終了いたしました。

125:デフォルトの名無しさん
07/01/06 23:09:40
>>123
うむ御旗楯無もご照覧あれ

126:デフォルトの名無しさん
07/01/08 22:40:26
実験用にものすごく単純なマルチスレッドの http サーバを組んでみたのだけど、
コードだけ見るとロックするようなコードじゃないのに、長時間ストップしたまま
になることがある。(いちおう、しばらく待つと再開する)

listen() 状態のソケット作って、accept() したら pthread_create() してループ。
子スレッドのほうでは GET (path) HTTP/1.1 を待って、そのファイルを読んで返すだけ。

という単純なやつなのだけど、毎秒100リクエスト以上くらい httperf で送ってやると、
必要以上に処理がストップする。
(netstat -a すると一つも ESTABLISHED になっていない状態で数秒間とまっている)

カーネルは NUMA を無効にした以外は特にいじっていない Linux 2.6.15.7/x86_64
スレッドとネットワークをがんがんいじっている人には自明な問題っぽいけど、
どの辺に原因があって、どういじれば、せめて無駄なストップをしなくなるのでしょうか。

127:デフォルトの名無しさん
07/01/09 11:26:21
>>126
親スレッドでpthread_joinなり、pthread_detachしてる?
してないと、終了コード保持のため、子スレッドが終了せず、プロセスのスレッド数限界に
引っかかるかもしれん。

128:デフォルトの名無しさん
07/01/09 17:27:41
いちいちaccept毎にthreadを作成・破棄というのが良くない予感

129:デフォルトの名無しさん
07/01/09 19:18:57
>>126
子スレッドはちゃんjとソケットから全部読んでから closeするか、shutdown するかしてますか?

130:デフォルトの名無しさん
07/01/09 21:36:43
FreeBSDでコンパイル&実行するとそういう問題は起きない

131:デフォルトの名無しさん
07/01/16 22:08:14
_endthreadでスレッド終了すると、デストラクタが走りません。
無理やり{}で囲んでデストラクタを走らせてますが、
標準的な方法ってありますか?

132:デフォルトの名無しさん
07/01/16 22:17:40
_beginthreadは使わない
_endthreadexは呼ばない

133:デフォルトの名無しさん
07/01/16 22:29:22
>>132
_beginthreadexを使い、スレッド終了時に_endthreadexを呼ばないで単にreturnするだけということでしょうか??

134:126
07/01/16 23:37:42
ISP が割り当てるアドレスの周辺が 2ch にブロックされて書き込めなかった…。

スレッドとは関係なく、プロセス (もしくはある listen 状態のソケット)
あたりの同時接続数が一定値を超えると何かあるのかも、とか推測中。

>>127
pthread_detach() してますね。
>>128
待機スレッドを用意しておくとかすると改善するのかな。
>>129
あ、読み残しがある可能性はあるかも。
けど、そういう原因ならリクエスト頻度を下げても同様の問題が起こり
そうなものだが、 50リクエスト/秒くらいにすると起こらなくなる。
>>130
ソケット一般の問題じゃなくて Linux 特有の問題か…。

135:126
07/01/16 23:39:44
あ、とりあえず接続数を減らして、一接続あたりの転送量を増やすことで
目的には事足りるので、とりあえずそのようにしてやっている。

なぜストップするのか、に対する興味はあるのでまだ調べているけど。

136:デフォルトの名無しさん
07/01/17 18:05:57
tcp_fin_timeout の話かなぁ
再利用できるポートが足りなくなって、待ちになってるとか

137:126
07/01/17 22:48:11
>>136
あ、それビンゴかも。

Apache に細工して、一度ソケットを (勝手な手順で) 作り直してアクセスすると、
同様の停止現象が起こった調査結果が手元にある。

ソケットに何かの値を設定すると停止現象を回避できるのかなあ
(Apache は標準でそれをやっているけど、自分の勝手な手順ではやっていないのが原因かなあ)
と想像していた。 setsockopt() で *ソケットごとに* この tcp_fin_timeout を
設定できるらしいので、この値がそれかもしれない。

これから Apache のソースを読んでみるつもり。 thanks.

138:デフォルトの名無しさん
07/01/17 23:11:05
>>134
>あ、読み残しがある可能性はあるかも。

ソケットは、両端で正しく
・全部読む (read で 0 が戻るまで)
・shutdown する
のどちらかをしないと、close しても FIN_WAIT_2 だか何だか長めに待たされるステートに
なっちゃっうんじゃ無かったかなあ。netstat してみれば即わかるけど。

URLリンク(www.kt.rim.or.jp)
の mini FAQ の 5 を参照。

139:デフォルトの名無しさん
07/01/19 12:09:34
スレッドがシグナル状態になったあとに新たにスレッドを生成したいのですが、
そのスレッドのハンドルはクローズした方が良いのでしょうか?
シグナル状態になったらスレッドのスタックは解除されるようですが。
上書きしてCreateThreadをしたらメモリリークしたりしますか?
Win32APIです。

140:デフォルトの名無しさん
07/01/19 12:36:33
クローズした方が良い

141:デフォルトの名無しさん
07/01/19 23:23:03
ハンドルってただのポインタだから、
上書きしてもポインタ先が変わるだけ
リソースは残ったままだとおもう

142:デフォルトの名無しさん
07/01/19 23:30:08
スレッドが終了してシグナル状態になったんであれば、
スタックとかコンテキストは解放されると思うけど
ハンドルは残ったままじゃないか?戻り値を受け取るためにハンドルが必要だし。
といっても、ハンドルごとき残ったままでもたいしたことは無い。
(少々のリソース漏れはたいしたことないなんて言ってる奴のコードは信用ならんけど)

143:デフォルトの名無しさん
07/01/20 01:01:12
試してみた。
#include <stdio.h>
#include <windows.h>
static DWORD WINAPI func(LPVOID p) {
printf("thread %d\n", (int)p);
return 0;
}
int main() {
int i;
for(i = 0; ; i++) {
if (::CreateThread(0, 0, func, (LPVOID)i, 0, 0) == 0) break;
}
::getchar();
printf("i = %d error code %u\n", i, ::GetLastError());
::getchar();
}

VS2005のデバッガ上だと2000超えたあたりでERROR_NOT_ENOUGH_MEMORYで止まる。
デバッガ外でやってみたら10万超えても終わらず、
なぜかipoint32.exeにアプリケーションエラーが出たりして怖くなったのでやめた。

144:デフォルトの名無しさん
07/01/21 13:15:48
メモリリークか 何もかも(ry

145:デフォルトの名無しさん
07/01/21 15:01:28
func のスレッド優先度、上げといた方がいいのでは?


146:143
07/01/22 08:17:30
あーそっか。あくまでハンドルのみのテストだったらちゃんとWaitForSingleObjectで待たなきゃいかんわな。
しかしWaitForSingleObjectしたのにわざわざCloseHandleしないでおく理由って考えにくいが。

147: ◆0uxK91AxII
07/01/22 19:48:12
CreateThreadで走らせたthreadでは、CRTのfunctionを呼ぶべきではない。

148:デフォルトの名無しさん
07/01/22 20:37:55
メモリーリーク?

149:デフォルトの名無しさん
07/01/23 00:11:40
再入?

150:デフォルトの名無しさん
07/01/23 01:46:25
URLリンク(d.hatena.ne.jp)
こんな話もあった。

151:デフォルトの名無しさん
07/01/24 19:22:25
とりあえずCRTは動的リンクしておけと

152:デフォルトの名無しさん
07/02/02 23:38:46
2つプロセスで共有メモリのデータを共有する
サンプルってどこにあるのですか?pthread Linuxのやつを探しています。

153:デフォルトの名無しさん
07/02/03 09:49:27
スレッド関係ないから。APUE買え。

154:デフォルトの名無しさん
07/02/03 10:21:08
VS2005って標準でOpenMP使えたんだな

155:デフォルトの名無しさん
07/02/18 16:38:41
ここで俺がひとまずここまでのレスをまとめる。

マルチスレッドは ム ズ カ ス ィ

156:デフォルトの名無しさん
07/02/18 20:05:23
>>152
だまってmmapすればいいんでないの?

157:デフォルトの名無しさん
07/02/18 21:12:05
>>155
お前にこの言葉を授けよう
「糞スレ立てるな」

158:デフォルトの名無しさん
07/02/20 23:27:34
ファイアーモックス!

159:デフォルトの名無しさん
07/02/24 10:27:57
質問なんですがマルチスレッドでは同じ変数のアドレスの場所を
if文等で見に行くだけならぶつかることはないですか?

160:デフォルトの名無しさん
07/02/24 10:34:52
読むだけなら問題ないと思。
最適化には気をつける必要があるが。

161:デフォルトの名無しさん
07/02/24 10:40:11
FAQだな。
読むだけなら排他不要。
ただしvolatileを忘れずに。

つーかvolatile最強。

162:デフォルトの名無しさん
07/02/24 12:17:45
>>159-161
別スレッドからの書き込みも考慮するならロックなどによる同期が必要。

volatile はネタだよね?

163:デフォルトの名無しさん
07/02/24 12:46:43
他スレッドが変更するメモリを読むなら必要でしょ。

164:デフォルトの名無しさん
07/02/24 13:02:15
おっ久々にvolatileが来たか。わくわく。

165:デフォルトの名無しさん
07/02/24 13:16:54
>>162
writerが一人、readerが複数ならロックする必要ないよ。

166:デフォルトの名無しさん
07/02/24 13:28:17
>>165
あたまだいじょうぶか

167:デフォルトの名無しさん
07/02/24 13:28:40
意地悪しないで教えてやれよって。
JavaやC#でのvolatileはその解釈であってる。
C/C++のvolatileは割り込みしか想定していないので、マルチスレッドでの動作は不定。
ただしシングルCPUでのマルチスレッドは割り込み(タイマー割り込み)で実現されているのでたまたま動作する。

>>165
変数がアトミックじゃない場合、例えば32bitCPUで64Bitの変数にアクセスする場合などは、
書いてる最中に読み込みされると半分しか書き換わってない状態を読み込む可能性がある。

168:デフォルトの名無しさん
07/02/24 13:34:19
シングルCPUのマルチスレッドだと動いてしまうことが多いからね。それで合ってると思い込んでしまうのだよ。
CPUキャッシュの問題は難解だね。
さらにウィークメモリモデルともなるとさすがについて行けんorz

169:デフォルトの名無しさん
07/02/24 13:43:29
書き込み側が明示的に、アトミック書き込み命令を出せばいいんでね?

170:デフォルトの名無しさん
07/02/24 16:37:41
読み込みもアトミックじゃねーと意味ね-よ

171:デフォルトの名無しさん
07/02/24 16:41:40
要は、アトミックに読み込めることが期待できるint程度のデータ以外はなんらかの排他が必要ということでよろしいか。
#いや、intでも排他するべきなのかもし煉瓦。

172:デフォルトの名無しさん
07/02/24 18:52:05
>>171
> #いや、intでも排他するべきなのかもし煉瓦。
というのが>>168だね

マルチCPU環境の排他はバス設計の影響もうけるから
環境を明記しないと言及不能やね


173:デフォルトの名無しさん
07/02/24 20:21:33
>170
書き込みがアトミックに出来るのに、読み込みがアトミックに出来ない、なんて
変態CPUが現存するのか?そういうCPUではロックをどう実装するんだろ?

174:デフォルトの名無しさん
07/02/24 23:09:38
キャッシュラインをまたぐと面白いよねー


175:デフォルトの名無しさん
07/02/25 01:29:43
>書き込みがアトミックに出来るのに、読み込みがアトミックに出来ない、なんて
>変態CPUが現存するのか?

>書き込み側が明示的に、アトミック書き込み命令を出せばいいんでね?

>読み込みもアトミックじゃねーと意味ね-よ

だれも読み込みがアトミックにできないなんて言っとらんわ。


176:デフォルトの名無しさん
07/02/25 04:26:18
どっちかというと
>ねーと  → ー
>ね-よ  → -
この不整合の方が気になるな
どちらかがアトミックじゃないのかもしれない

177:デフォルトの名無しさん
07/02/25 05:04:12
こういう意味不明な誤変換はUNIX発のFEPwに多いな

178:デフォルトの名無しさん
07/02/25 15:04:49
volatile方式を知られては困る奴が必死だなw

179:デフォルトの名無しさん
07/02/25 15:39:00
URLリンク(d.hatena.ne.jp)
volatile無意味説

180:デフォルトの名無しさん
07/02/25 17:24:44
そのリンク先にしても、なぜvolatileでは駄目なのかが書いてなくて
「お母さんが駄目って言ってたから」レベルの話しか書いてないな。
そして、そのURLを貼る>>179も同様。

181:デフォルトの名無しさん
07/02/25 17:50:33
なぜ volatile で済むと言えるのか、書くかリンク貼るかしてみやがれ。

182:デフォルトの名無しさん
07/02/25 18:59:13
volatile - Multithreaded Programmer's Best Friend
URLリンク(www.ddj.com)

183:デフォルトの名無しさん
07/02/25 19:32:05
>>182
もしかして >>181 へのレスのつもりなのか?

184:デフォルトの名無しさん
07/02/25 19:41:48
そんなわけないだろ。逆だ。
"Paradoxically, it's worse to use volatile directly with built-ins, in spite of the fact that initially this was the usage intent of volatile!"

185:デフォルトの名無しさん
07/02/25 20:20:26
>>182
これって
>スレッドセーフなメソッドにはvolatileをつける。
という提案だよな?まだ実装はないと思ったのだが。

186:デフォルトの名無しさん
07/02/25 22:48:59
volatileを実装してるJVMってほとんど無いんじゃなかったっけ

187:デフォルトの名無しさん
07/02/25 23:35:03
>>185
実装ってどういうこと?標準 C++ コンパイラがあれば使える手法に見えるんだけど。

188:デフォルトの名無しさん
07/02/26 01:31:15
C とか C++ の volatile って I/O レジスタとか, 割り込み同期変数とかを, オ
プティマイザがレジスタキャッシュしないように指示するために導入された物で,
バリア同期命令とか生成する処理系は皆無のような気がするが...

俺の認識が古くって, バリア同期とか生成してくれる処理系が既にあるんだった
ら先にあやまっとく


189:デフォルトの名無しさん
07/02/26 05:30:32
何故「volatileで済む用途」のケースにメモリバリアがどうのという話になるのかわからんね。

簡単な例で言えば
(タイマ割り込み等で更新される)カウンタを読む場合とか
複数スレッドで値を読み取るとしても、ロックする必要なんか無い。
たとえ1ns更新が遅れたって、問題が出ることは無い(問題が出るようなら、設計がおかしい)。

え、更新時の再入を考慮しろって?
そういうのを「設計」と言うんだろうに。

190:デフォルトの名無しさん
07/02/26 06:29:25
>>182
int func() const { } はよく使うが、int func() volatile { } を実際に使ってる例ははじめてみる。
ただその記事のLockingPtrは func() volatile の仕組みだけ拝借して実際の排他はmutexでやってるようだ。
よく理解できない部分もあるがvolatileしておいてconst_castで限定的に穴あけてるのだろうか。
このスレで問題になるのはそこではなくて、
記事の最初と2番目のコードで while (!flag_) のflagがvolatileだけでいいのか、
同期機構を使わなくてはいけないかのポイントだと思う。


191:デフォルトの名無しさん
07/02/26 07:52:54
>>188
volatileで済むってのは、コヒーレントキャッシュを持っている環境で
アトミックに読み書きできるサイズ限定だから、メモリバリアは関係ないよ。
2つ以上の変数に依存関係があったら、volatileだけでは無理。

一般論の話をすれば、キャッシュの一貫性を保障しない環境もあるから
int程度でもvolatileでは駄目という話になるが。

192:デフォルトの名無しさん
07/02/26 09:15:17
ちゃんと読めてないが、>>182って、コンパイラの実装とか関係なくて
constみたいな印としてvolatileを使ってみようっていう提案だよね?

193:デフォルトの名無しさん
07/02/26 19:26:29
volatileの仕様は処理系定義だとあれほど言ってるのに…

処理系を指定しないでvolatileについて語れることはない

194:デフォルトの名無しさん
07/02/26 21:25:32
処理系どころか言語すら指定されてない気がするのは
漏れだけではないはずだ

195:デフォルトの名無しさん
07/02/27 00:02:42
とりあえず、volatileをCの最適化阻害だけと仮定して、

>>191
一貫性を保証しなかったとしても、それはあくまで保証の話。
いつまで経っても同期されないような腐ったCPUってあるの?
あったとしたら処理系としてBrokenだよなぁ・・・。

>>193
ここに書いてる人のほとんどは処理系依存だなんて承知の上でしょ?


とりあえず、intだとしても同期やメモリーバリアは必要か?
って問いはもう少しレベル分けした方がいいと思う。

1. 読み込みに依存した書き込み(read-modify-write)
⇒ 同期もしくはメモリーバリアを含んだCASが必要。

2. 読み込みに依存しないが、確実に更新を見る必要がある
⇒ OoOを回避するために、少なくともメモリーバリアは必要。

3. 読み込みに依存しないし、更新は近いうちに反映されればよい
⇒ volatileでレジスタへの張り付きを阻害するだけで問題なし?

>>189の「更新が遅れても構わない」は3になると思うんだが。

196:デフォルトの名無しさん
07/02/27 01:19:13
つまり、例えば時間掛かる処理をするスレッドがあってその進捗をプログレスバーに出すような用途なら、
進捗を書き込むのを処理スレッドに限定してGUIスレッドでそこをvolatileで参照するのもありってことでOK?

197:デフォルトの名無しさん
07/02/27 01:57:30
マルチスレッドの話は環境によって差異がありすぎるから
環境を限定しない討論に何の意味もないって感じだな。

198:デフォルトの名無しさん
07/02/27 03:01:55
volatile最強伝説が吹き荒れるwww

199:デフォルトの名無しさん
07/02/27 08:43:30
> 195
> とりあえず、volatileをCの最適化阻害だけと仮定して、

曖昧な仮定だな。
まずはお前の想定している処理系と、そのマニュアルにある
volatile参照の仕様を書くんだ。

200:デフォルトの名無しさん
07/02/27 09:11:34
もう>>182みたいにvolatileキーワード使って組込型でも何でもロック必須にしちゃいなyo!
template <typename T>
struct NativeWrapper
{
operator T&() { return obj; }
private:
T obj;
};

volatile NativeWrapper<int> syncint;
mutex mtx;
LockingPtr<NativeWrapper<int> > pInt(syncint, mtx);
*pInt = 10;

201:195
07/02/27 12:18:08
>>196
そんなとこ。他ではTwo-Phase Terminationの終了フラグとか。
こちらの場合はメモリーバリアを含んだ同期をループの内部で
実行する事が殆どだから、次のループで確実に気付くだろうけど。

>>197,199
おまえら処理系依存って書きたいだけだろ?
実際のとこはどうなのか、って話がしたいんだよ。

少なくともOoOやコヒーレンシが問題になるんだから、
最低限SMP/Multi Core/HT等のアーキテクチャとなる。

例えばIA-32,Power PC,Sparc等のSMPの類をサポートした
アーキテクチャのうち、>>195よりも厳しい制約が必要と
なるものは存在するの?

202:デフォルトの名無しさん
07/02/27 13:04:58
>>201
個々の CPU について考えるなんて面倒だから、
保証されてるかどうかで話したほうが楽なのに。

今は無くても将来にわたって無いとも言えないしね。

203:デフォルトの名無しさん
07/02/27 14:04:14
>>193
データ構造上の都合か何かでキャッシュラインをまたぐような位置から
int を読み込む場合には 3 もだめじゃないかな。

204:デフォルトの名無しさん
07/02/27 14:12:43
>>201
Intel Itanium では、非共有キャッシュが大きい上にキャッシュフラッシュの順序が
書き込みの順序と異なる。ので、

・volatile int a を監視
・aが変更されたら「何か」を行う

という処理の場合、大抵は「何か」の準備が出来たから a を1にしてるんだと思うけど、
メモリバリアが無いとその準備の処理結果を読み出せない可能性がある。

例) volatile size_t buflen; volatile char buf[max_buf]; で、
スレッド1: buflen = read(hoge); ...
スレッド2: if (buflen>0) { bufを利用; }
で、(スレッド2側のCPUから見て)buflen には read の結果のバイト数が書かれているが、
buf の内容はデタラメ、という状況がごく当たり前にあり得る。

205:195
07/02/27 14:54:42
>>203
キャッシュラインをまたぐ場合って、普通のコードじゃ起きないし、
char buf[sizeof(int)+1]; *(int *)(buf+1) = 0;した場合とかでしょ?
今では例外飛ばさずにアクセスできるアーキテクチャの方が少数派なのでは?

>>204
他の変数を確定的に見る必要がある場合はOoOの関係で無理。
>>195はひとつのintを扱う場合なつもりで書いてます。

>>196を例にすると、タイマでプログレスバーを更新する時はvolatileのみ、
最後に終了したかを確定的に判断したい時だけpthread_join()するケースとか。

206:デフォルトの名無しさん
07/02/27 15:21:57
>>205
PCで使われているCPUの98%は、それをごく普通に実行します。
任意位置からの32bitの整数読み出しはMPEG系のビデオコーデックの
処理では多利用されるし。

207:195
07/02/27 16:11:02
CPUの数が多いのは当たり前だからアーキテクチャって書いたのに。
そんな下らないツッコミは要らないって。。

Codecの処理だろうが、境界整列に反したメモリアクセスなんて
行儀の悪いコードなんじゃないの?少なくともポータブルじゃない。
処理系依存のレベルで言ったらvolatileの比じゃないと思うんだけど。

208:デフォルトの名無しさん
07/02/27 16:25:35
アーキテクチャの数で言って多いか少ないかについては、
漏れは何も言っていません。

実存するシステムの大半では割合で例外は飛ばないという
(関連する)別の事実を提示しただけですよ。

209:195
07/02/27 18:33:40
>>208
おまえ例外が飛ばないって書きたいだけだろ?
実際のとこはどうなのか、って話がしたいんだよ。


210:デフォルトの名無しさん
07/02/27 19:55:55
理屈で勝てそうにないと急におまえ呼ばわりですか。

実際の例で言うなら、MPEGのシステムストリームから4バイト長さの整数を取り出すとき、
ポータビリティを重視している ffmpeg ではバイト単位で取り出して整列してますし、
IA32/64が前提のIPPではポインタをそのままデリファレンスしてアライメントを気にせずに整数を取り出してます。

「普通のコードじゃ起きないし、例外飛ばさずにアクセスできるアーキテクチャの方が少数派」だから、
キャッシュラインまたぎの問題は無視してよいとでも言いたげな感じですが、
実際のとこどんなプログラムをどれだけ調べた上で書いてるんですか?

211:デフォルトの名無しさん
07/02/27 20:59:04
IA86において、そもそも、アラインメントが狂った位置への
アトミック書き込みはできない。

212:デフォルトの名無しさん
07/02/27 21:54:58
傍から見てるモノとしては
実装の詳細じゃなくてアーキテクチャの視点で語ってほしいです><

213:デフォルトの名無しさん
07/02/27 22:12:28
「相談室」なんだから、なにか適当なターゲットを想定するのが普通だろ
メタ論がやりたいならどっか適当にスレ立てろよ

これがほんとにマルチスレッド

214:デフォルトの名無しさん
07/02/27 23:34:05
そういうアクセスははなからそういうあくせすという前提で特別に処理を書くんじゃないの?
intでもアトミックに読めないとか、そういう問題とは別次元だろ。


215:デフォルトの名無しさん
07/02/27 23:35:07
わざとあえて意識してそういうことをしないとそういうことは起こらない。


216:195
07/02/28 01:26:31
>>210
>>209は自分じゃないんで・・・。

他の方も書いているように、CodecみたいにCPUベタベタな
最適化を行う場合を考えてもしょうがないかと。

今のところは>>189>>196みたいなケースの場合にvolatileで
不十分な証拠は(処理系依存を除いて)出ていないんじゃないですか?

そんなわけで、今のところ>>180から進展はなさそうに思います。

>>213
自分はPCサーバクラスで使われるCPU辺りをメインに書いてます。
今はノートですらDual Coreだったりするので、その辺りも含めて
昔で言うワークステーションクラスまででしょうか。

217:デフォルトの名無しさん
07/02/28 02:53:24
言語組み込みの volatile で全部済ませられると主張するなら、
「あぁそうだといいね」とも思えるが、場合によってはロックが必要なことは
理解しているようだし。そうなると細かいこと考えずに全部ロックしとけば
いいと考えそうなもんだ。

なんでそんなに必死になってまでロック使いたくないの?
わざわざ保証されてないコード書くメリットが何かあるの?

218:デフォルトの名無しさん
07/02/28 06:28:24
このスレは頭ごなしにmutex使えやゴラーというやからが多いから意固地になってるのだろう。
結論はそうなんだけど、そこに至る過程を検証したいというのも分からないではない。
mutexの中の人が何をやっているかとか、実際身近にあるPCで賢い小人さんがどう働いているかとか、
そういう話題なら問題は無いだろう?

219:デフォルトの名無しさん
07/02/28 13:20:29
>>217
>なんでそんなに必死になってまでロック使いたくないの?
実行コストに決まってるだろ。
実行コスト無視できるなら、スピンロック、read-writeロック、プロセス内Mutex、プロセス間Mutex、
の使い分けなんて必要ない。
ただ、volatileで生成されるコードと、他のロックでどちらがコストが高いかは知らん。実行系によるし。

220:デフォルトの名無しさん
07/02/28 13:51:46
スレッド間で変数を共有する場合問題になるのは次の4つくらいか。
1)変数のレジスターへのキャッシュ。
2)コンパイル時の命令の並び替え。
3)CPUによる命令の並び替え(out of order)
4)CPUキャッシュ間の非同期。

1,2はコンパイラの仕事。
3は単一CPUでは発生しない。マルチCPUでは両方のケースがある。
4は単一CPUでは発生しない。マルチでもコヒーレント(一貫性)が保障されている処理系が多い。
3,4が発生しないでメモリー更新の順番が正しく見える構成をstrong memory orderと呼ぶ。

volatileだと1,2でかつアトミックな操作ができる単独の変数のみ。
メモリバリアは1,2,3,4すべてを満たしていて、
同期系のファンクションを使えばメモリバリアは適切に適用される。
書き込みが1スレッドで多数の読み込みスレッドがある場合に通常のLockが負荷が高いようなら、
ReadWriteLockとかInterLockとかそういったものを検討すべきだろう。

221:デフォルトの名無しさん
07/02/28 13:57:54
>>195
>いつまで経っても同期されないような腐ったCPUってあるの? 
>あったとしたら処理系としてBrokenだよなぁ・・・。 

ないとは言い切れない。互換性、安全性をとるなら同期ファンクションを使っておこう。
windowsXPまではstrong memory orderを前提にしているらしい。
MSDNのvolatileの説明が変なのはこのためだろうか。
移植性を無視してターゲットを絞るなら独自にいろいろやるのもありかもしれないが、
windows2003(今のところItanium用だけらしいけど)からは上記の3,4があるweak memory orderも
視野にいれているらしいから、こういうヴァージョンアップ時に困るな。

222:デフォルトの名無しさん
07/02/28 17:09:18
組み込み用だとキャッシュの同期なんて全くしない環境もあるようだが、
(そもそもCPUがマルチプロセッサ用に作られていない)
そういう環境にマルチスレッド対応のOSが移植されてるかは、
ググってみたが見つからなかったな。

一昨年あたりから、組み込み用CPUでもキャッシュ同期メカニズムを
持った物が出てきたようで、SMP対応のlinuxが移植されてたりするけど。

223:195
07/02/28 17:27:11
>>218
ほぼそんなとこです。

あとは、なんでPOSIX ThreadsにCASがないのか、とかね。
プリミティブ志向な設計なんだから追加されてもいいのに。
有名どころのアプリのいくつかは自前で実装してたりするし。

>>221
そりゃないとは言い切れないでしょ。

でもそういうのって、二の補数表現や1byte=8bitを仮定して
プログラムを書くのは良くないってのと同じなんじゃないの?
1word=36bitみたいな変態アーキテクチャを相手するのと一緒。

224:デフォルトの名無しさん
07/03/01 00:19:15
_beginthreadの使い方について質問です。
子スレッドの処理が止まっているとき、終了する方法が知りたいです。

-----------------------------------------------------------------
//子スレッドの関数
void thread_func(){
//Sleep();やソケットのaccept関数など永久に待つ関数などで、
//処理が止まっているので終了状態になりません
}
//子スレッド呼び出し
thread_id = _beginthread(thread_func,0,(void *)param)
//終了処理
GetExitCodeThread( thread_id,lpExitCode );//終了コード取得
ExitThread(lpExitCode );//終了コード指定して終了
CloseHandle(thread_id);//ハンドル閉じる
-----------------------------------------------------------------
1、子スレッドのsleep、accept関数など待ち状態を、解除する方法あるでしょうか?
処理が進めば、_endthreadで終了することが出来きるのですが。

2、強制的に親スレッドから、安全に子スレッドを強制終了する方法あるでしょうか?
_beginthreadは、CreateThreadを呼んでるみたいなのですが、上記のように
"//終了処理"しても大丈夫でしょうか?安全な方法教えていただけないでしょうか。

よろしくお願いします。

225:デフォルトの名無しさん
07/03/01 00:19:22
>>223
なんで良くないと言われていることをわざわざやりたがるの?

226:sage
07/03/01 00:43:41
>>225
良くないって、仕様で未定義だからってだけでしょ?
検証もせずに「お母さんが駄目って言ってたから」な方が嫌。

227:デフォルトの名無しさん
07/03/01 01:06:04
>>226
最近のレスでロック API の仕様の根拠となるものはあらかた提示されたんじゃないの?

228:デフォルトの名無しさん
07/03/01 01:22:09
>>224
とりあえず、
・必要なら、子スレッドでは極力タイムアウトするAPIを使う
・_beginthread()の場合、スレッド関数の戻りで子スレッドのハンドルは自動開放されるので
 明示的に開放する必要はない
・少なくとも_beginthread()のハンドルにCloseHandle()を使うのは間違い
 きちんと対応する関数をセットで使わなければいけない
・ただ、親スレッドでExitThread()したら、その後のCloseHandle()は実行されないよ
・子スレッドの安全な中断方法はない。

突っ込み所満載すぎるので、MSDNなりナニなりよく読むべし。


229:デフォルトの名無しさん
07/03/01 03:23:13
>>228
タイムアウト処理を考えるという方針でいきたいと思います。

sleepは時間を短くすればいいですし、
acceptは、selectを使ってrecvのタイムアウト関数(timeoutRevcとします)
と同じにすれば、timeoutAccept関数作れるかもしれないです。
・timeoutAccept抜けたら、はじめの一回目は、ソケットが読み込めるのわかってるので普通のrecv関数を呼ぶ。
・次の受信から、timeoutRevc呼ぶ感じでしょうか。

いくつも箇条書きでアドバイス、ありがとうございました。

230:デフォルトの名無しさん
07/03/01 07:04:23
229です。
acceptする前に、select関数使えないんでしょうか。

FD_ZERO(&readfds);
FD_SET(soc,&readfds);
select(width,&readfds,NULL,NULL,&timeout)
socは、きちんと渡せていたんですが、接続試しても
select抜けられずに、全部タイムアウトになります。
accept呼んでからじゃないと、ソケットの読み取り可能か
わからないかもです。

スレ違いになりますので、ネットワークのスレに行きたいと思います。
ありがとうございました。

231:デフォルトの名無しさん
07/03/01 11:14:25
やべーvolatile最強すぎる

「volatileが最強でない環境って存在するの?」
「現存しないからvolatile最強wwwwwwwwwwwwwwwwwwww」

>>161 でFA出てるしwww

232:デフォルトの名無しさん
07/03/01 11:18:50
2000年問題に通じるものがあるな

233:デフォルトの名無しさん
07/03/01 12:28:10
[すれ立てるまでもない質問はここで]
で聞いてたんだが、此処で聞いた方が良いかと思ったので、
再質問させてもらいます。

Windows MFCでマルチスレッドは止めておいた方が良い
と、良く聞くんだけど、具体的にどんな問題が発生するのか
掲示しているところが無いんだけど、どうしてMFCでの
スレッドは嫌われるのか教えてもらえないでしょうか。
単なる好奇心なので、仮説でもうれし。


234:デフォルトの名無しさん
07/03/01 12:42:43
誰が言ってんだ、そんなこと。

235:デフォルトの名無しさん
07/03/01 12:48:10
>>233
それま色々なスレで同じ質問をしないほうが良いと言われただけでは?

236:デフォルトの名無しさん
07/03/01 12:50:14
>>233
とりあえず移動元に誘導書いておけよ、マルチ扱いされるぞよ。
俺も聞いたことない。

237:デフォルトの名無しさん
07/03/01 13:27:04
MFCに限らず、マルチ(複数の)スレッドで質問するのは良くない。

238:デフォルトの名無しさん
07/03/01 14:21:41
ワロタ

239:デフォルトの名無しさん
07/03/01 16:05:38
>>224
URLリンク(support.microsoft.com)


240:233
07/03/01 16:17:27
>>234
>MFC のシステムそのものがマルチスレッドに向いていない。
URLリンク(www.kab-studio.biz)
さすがにどこで見たかを思い出せなかったので検索して
出てきたのが例えばこれとか。

>>236
>>237
移動元に書いてきたよ。
ごめんよ。


241:デフォルトの名無しさん
07/03/01 17:05:31
>>240
WaitForSingleObjectで待つんじゃなくて自イベントで通知
MFC関係なくないか?
読みづらいし会話式がアレだな

242:デフォルトの名無しさん
07/03/01 17:17:57
UIスレッドは確かに使わないかもしれない。向いてないとか難しいとかいうより必要性が薄い。
ワーカースレッドについては特にMFC特有の問題じゃないな。

243:デフォルトの名無しさん
07/03/01 18:03:52
>>240
じゃあ、そのサイトが間違い。
いや間違いというか、MFCがマルチスレッドに対して便利な機構を用意しているかというとNoだけど、
マルチスレッドを意識してないわけじゃない。つまり、ユーザーからロックできないグローバル変数、
クラス変数はロックしてる。
なんで、ユーザーからロックできる部分については、勝手にロックして、スレッドセーフにしろよ、
ってスタンス。それを「向いてない」と表現するかどうかは人による。
・MFCとマルチスレッドの関係 (Afx...でのMFCグローバル情報へのアクセス等)、
・Win32とマルチスレッドの関係 (SendMessageがらみのウィンドウループの把握、WinSockでのWM_を使った非同期処理等)、
・一般的なGUIシステムにおけるマルチスレッドの作法 (GUIスレッドを止めない、長時間処理は別スレッド、非同期化等)
を分けて考えるべき。


244:デフォルトの名無しさん
07/03/01 18:24:21
まぁMFCはガベコレがないという致命的欠点を持っているなんて
Wikipediaに書かれるほど挫折した連中に嫌われているってことだな。

245:デフォルトの名無しさん
07/03/01 18:47:00
> それを「向いてない」と表現するかどうかは人による。
「俺はマルチスレッドなプログラムなんかできないから、ライブラリか何かでどうにかしてくれよ」という人?
「これさえ使えばあら不思議。マルチスレッドなプログラムが簡単に!」とか。

>まぁMFCはガベコレがないという致命的欠点を持っているなんて
これは笑いどころですか?


246:243
07/03/01 19:03:59
>> それを「向いてない」と表現するかどうかは人による。
>「俺はマルチスレッドなプログラムなんかできないから、ライブラリか何かでどうにかしてくれよ」という人?
>「これさえ使えばあら不思議。マルチスレッドなプログラムが簡単に!」とか。

いや、俺に言われても。

247:244
07/03/01 19:38:14
>>245
> これは笑いどころですか?

いや、俺に言われても。

248:244
07/03/01 19:57:04
>>247
いや、そこで騙られても。

249:デフォルトの名無しさん
07/03/01 21:02:37
MFCにガベコレを求めるとかバカとしか思えない

250:デフォルトの名無しさん
07/03/01 21:11:36
244はそんなことを言ってるわけじゃないんだが。
改行位置のせいで勘違いするのも分からんでもないが。

251:デフォルトの名無しさん
07/03/01 21:27:35
このスレのガベージをコレクトしたい

252:デフォルトの名無しさん
07/03/01 22:08:15
       / ____ヽ           /  ̄   ̄ \
       |  | /, -、, -、l           /、          ヽ
       | _| -|  ・|< ||           |・ |―-、       |
   , ―-、 (6  _ー っ-´、}         q -´ 二 ヽ      |
   | -⊂) \ ヽ_  ̄ ̄ノノ          ノ_ ー  |     |
    | ̄ ̄|/ (_ ∧ ̄ / 、 \        \. ̄`  |      /
    ヽ  ` ,.|     ̄  |  |         O===== |
      `- ´ |       | _|        /          |
         |       (t  )       /    /      |
「>1からマークスイープでGCするよ!」   「コンパクションも忘れずにね」

1時間後…

      ,-―-、                         ___
      { , -_-_-                        /  _   _ ヽ
     .(6( /),(ヽ|                       /  ,-(〃)bヾ)、l
     /人 ー- ソヽ _                    | /三 U  |~ 三|_
  /  /  |  ̄_∧/   ヽ                   |(__.)―-、_|_つ_)
      | |  \/_/-、    /                  /  /`ー--―-´ /
      |-\ _|_ )_|   /                  |  // ̄( t ) ̄/
      ヽ-| ̄|  |_|_ /                 ,- |   | ヽ二二/⌒l
    /  l―┴、|__)                 |  (__> -―(_ノ
 /    `-―┘ /                   `- ´
           /
「>1しか残らなかった…」               「テンプレへのリンクもなかったのか!」


253:デフォルトの名無しさん
07/03/01 22:48:55
>>251
     [゚д゚]  ・・・?
     /[_]ヽ
      | |

254:デフォルトの名無しさん
07/03/01 23:53:37
>>253
おまえは呼んでない

255:デフォルトの名無しさん
07/03/04 02:15:45
pthreadのPTHREAD_MUTEX_INITIALIZERのように、
win32のCRITICAL_SECTIONを静的に初期化する方法はありますか。

現在は仕方が無いので
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
で済むところを
static pthread_mutex_t mutex;
static int initialized;
static int lock;
if (!initialized && InterlockedIncrement(&lock) == 1) {
  pthread_mutex_init(&mutex, 0);
  initialized = 1;
}
などと書きました。

なお、↑のコードでは、とりあえず
#define pthread_mutex_t CRITICAL_SECTION
#define pthread_mutex_init(A,B) InitializeCriticalSection(A)
#define pthread_mutex_lock(A) (EnterCriticalSection(A), 0)
#define pthread_mutex_unlock(A) (LeaveCriticalSection(A), 0)
#define pthread_mutex_destroy(A) DeleteCriticalSection(A)
などと定義しています(極めてうさんくさいですが)。

256:デフォルトの名無しさん
07/03/04 04:38:29
>>255
class CriticalSection
{
    CRITICAL_SECTION csect;
public:
    CriticalSection() { InitializeCriticalSection(&csect); }
    ~CriticalSection() { DeleteCriticalSection(&csect); }
    void Lock() { EnterCriticalSection(&csect); }
    void Unlock() { LeaveCriticalSection(&csect); }
    operator LPCRITICAL_SECTION() { return &csect; } 
};

class Lock
{
    CriticalSection& save_cs;
public:
    Lock(CriticalSection& cs) : save_cs(cs) { save_cs.Lock(); };
    ~Lock() { save_cs.Unlock(); }
};


257:デフォルトの名無しさん
07/03/04 04:40:47
static CriticalSection cs1; // で初期化しておいて下のように使える。

void func(){
    Lock lock(cs1);
    // 
}

void func(){
    cs1.Lock();
    // 
    cs1.Unlock();
}


258:デフォルトの名無しさん
07/03/04 05:07:50
というやり方だと、
コンパイラの吐く「ローカルな静的変数の初期化コード」に排他処理が行われないため
グローバル変数(staticメンバでも良いが)にしか使えない。

で、過去スレに書いたが
CriticalSectionへのポインタとInterLockedExchangePointerを使えば
ローカルな変数でも、排他しながらの初期化及び実行が行える。

259:デフォルトの名無しさん
07/03/04 05:21:53
なるほど。C++のstatic objectの初期化機能を利用する訳ですね。
Cでは使えないテクニックですね……。

>>255のコードには不備がありました。
2コ目以降のスレッドがInitializedCriticalSection()実行前に
下に流れてしまう可能性があるので、
上のコードの後で
while (!initialized) Sleep(1);
としなければなりませんね。


260:デフォルトの名無しさん
07/03/04 05:48:19
>>258
>で、過去スレに書いたが 
目を通しておきたいのですが過去スレというのはこのスレですか?その4以前?

最初のロックまでCRITICAL_SECTIONの初期化を遅延したいとか
考えない限り大丈夫のように思えるけど。

261:デフォルトの名無しさん
07/03/04 05:48:40
んー、だから

static CRITICAL_SECTION *p = NULL;
if (!p) {
 CRITICAL_SECTION *q = new ...;
 Interlocked...(&p, NULL, q); //引数の順番忘れた
 if (p != q) {
  delete q;
 }
}
EnterCriticalSection(p);
...
Leave...();

なら、Cでも使えるよ。

262:デフォルトの名無しさん
07/03/04 05:53:34
で、C++なら、これをclassにまとめて
#ifdef _WIN32 で切り分けてPTHREAD_MUTEX_INITIALIZERと使い分けると楽だよ。
ただ、必ずstaticなオブジェクトとして使わないといけない、ということを
分かった上で使わないといけないけど。

263:デフォルトの名無しさん
07/03/04 05:57:13
あ、Initializeとか忘れてたけど
まあ分かるでしょ

264:デフォルトの名無しさん
07/03/04 06:12:45
>>261
new, deleteがCでも使えるというのは冗談でしょう。

if (!p) {
 CRITICAL_SECTION *q = new ...;

これは、この部分に2コ以上のスレッドが同時に突入した場合、
2度以上InitializeCriticalSection()を実行させたいという意味ですか?


265:259
07/03/04 06:15:36
> while (!initialized) Sleep(1);

このように書きましたが、これはWin32環境で合法なのでしょうか。
マルチコアのシステムではまずかったりしますか。

MSVC++で-Ox最適化をかけたアセンブリコードを眺める限り、
一見動きそうに思えますが、いまいち自信がありません。

266:260
07/03/04 06:16:08
>>261
初期化を遅延する場合ですね。それなら了解。

267:デフォルトの名無しさん
07/03/04 07:08:09
>>264
newが使えない事くらい、わかった上で書いたんだけど(面倒だから)
そんな本質的じゃない部分を指摘してうれしい?

件の部分は、(ほぼ)同時に突入したら、当然複数初期化される。
けど、続く部分で、実際に代入されるのは一つであることが保証される。
(最初に実行されたスレッド以外からのCASは失敗する)
だから、それを実行した後、自スレッドで初期化した値とpが違っていたら
それを破棄して、全スレッド共有の値でロックを実行すればよいだけ。


まあ、俺が偉そうな事言いたくて書き込んだだけだから、あまり気にするな。
普通に非ローカルな静的変数とC++のインスタンス初期化を使うのが
いちばん簡単だし、わかりやすいし、無駄も無い。
初期化順が問題になることも無いでしょ。

268:259
07/03/04 07:17:53
>>267
> そんな本質的じゃない部分を指摘してうれしい?

気を悪くされたならすみません。
Cで書いた場合のコードに、>>255と本質的な違いがあるのか?と
問いたかっただけです。
newが使えないだけではなく、クラスも使えませんよね。
>>261は全くCのコードではありません。

> 件の部分は、(ほぼ)同時に突入したら、当然複数初期化される。
単に複数回初期化されるだけでなく、メモリリークが発生しますね。

269:デフォルトの名無しさん
07/03/04 08:14:12
> メモリリークが発生しますね。
だからわざわざ(本来なら省略しても良い)deleteまで書いたんだけど?

270:デフォルトの名無しさん
07/03/04 08:17:06
まさかとは思うけど
「実行中に確保(初期化)されて、終了時でも解放されないままのもの」
という意味で「メモリリーク」という言葉を使っている、
More Effective C++すら読んでないような初心者だったら、ごめんよ。

271:デフォルトの名無しさん
07/03/04 08:20:53
>>268
>>261はいろいろ省略してるのだけど、InterlockedCompareExchangePointerを使えといってるのだと思うよ。

>Cで書いた場合のコードに、>>255と本質的な違いがあるのか?と 
>問いたかっただけです。 

どちらも遅延初期化で本質的な違いはなさそうだけど、
>>261はダブルチェックロッキングが正しく出来ているが>>255には穴がある。



272:259
07/03/04 08:27:12
>>269
理解しましたm(_ _)m
他スレッドのInterlockedExchangePointer()によって値が変えられていたら
deleteするという意味なのですね。

Cで書くと
static CRITICAL_SECTION *p = 0;
if (!p) {
 CRITICAL_SECTION *q = malloc(CRITICAL_SECTION);
 InitializeCriticalSection(q);
 InterlockedExchangePointer(&p, q);
 if (p != q)
  free(q);
}
でしょうか。

273:259
07/03/04 08:30:03
んが。
malloc(sizeof(CRITICAL_SECTION));
ですね。

それと。InterlockedExchangePointer()ではなく、
InterlockedCompareExchangePointer()を使わなければならないのですか。

むずかしい...。

274:259
07/03/04 08:32:30
>>271
>>255のコードの穴というのは、>>259に書いたのとは別のものでしょうか。

275:デフォルトの名無しさん
07/03/04 09:21:12
あーそうか、ほんとごめん。
確かに>>271の通り、CompareExchangeの方のこと(つまり>>258が俺の凡ミス)。
俺が重要な部分を間違えていたのに、意図を理解してくれる人がいてくれて助かった。
他の人も含め、ごめんね。

>>259では、本質的な解決にならないと思うよ。
つまり、比較(テスト)と初期化(&代入)の間に他のスレッドに割り込まれる可能性を消すには
atomicなCASを実行するしかないって事。

276:デフォルトの名無しさん
07/03/04 09:31:57
あ、そうか、>>255を見るとInterlockedを使っているのか。
でも、InterlockedIncrementは正負と0しか判定できないんじゃなかったかな。

で、仮に
初期値を-1として
2^32個以上のスレッドが同時に初期化部に入ることは有りえないとして
>>259の修正(Inc失敗なら他のスレッドを待つ)を加えて
当然volatileにして
とすれば、正常に動くのかな。

でもそこまでするなら、やっぱりCASを使う方がまともかと。

277:259
07/03/04 09:40:12
>>276
はい。CAS方式がエレガントでまともなコードであると納得できました。
Sleep()ループで待つなんてカッコ悪いことは出来ればしたくありません...。
有難うございます。

278:デフォルトの名無しさん
07/03/04 09:45:22
ここまでやれば大丈夫だと思うけど。
if (!initialized)
 if(InterlockedIncrement(&lock) == 1) { 
  pthread_mutex_init(&mutex, 0); 
  initialized = 1;
    メモリバリア~~
 } else {
    while (!initialized) {
        Sleep(1);
        メモリバリア~~  またはinitializedが揮発性であることが必要
    }
 }
}
老婆心から言えばスレッド生成前までに作っておいたほうがよいと思う。
スレッド生成後の初期化なんてバグの元。
PTHREAD_MUTEX_INITIALIZERマクロが何をやってるか調べてみたら何かヒントがあるかもしれないね。
javaで有名になったダブルチェックロッキングの話はまだ半分くらいしか理解できてないしなorz


279:デフォルトの名無しさん
07/03/04 09:47:50
InterlockedIncrementはWin95以前だと正負と0の判定しかできないので>>255のようには使えないよね。

あと厳密に言えばの話だけど
このスレの上のvolatile関連の議論からするとinitialized=1;の変更がキャッシュのせいで
他のスレッドに伝わらないかもしれない(規格的には)ので>>255のinitializedにはlock命令が必要だけど
lock命令を追加しようとすると結局>>261みたいになってしまうんじゃないかな。

別に言わなくてもわかるだろうけど
>>255は volatile static int lock = 0;
>>272
volatile static CRITICAL_SECTION *p = NULL;
if (p != q) { DeleteCriticalSection(q); free(q); }

280:デフォルトの名無しさん
07/03/04 09:49:12
> PTHREAD_MUTEX_INITIALIZERマクロが何をやってるか
これはさすがに定数値を{}なりで囲んでるだけだと思うけど。
Cでも使えるんだし。

281:259
07/03/04 09:52:14
PTHREAD_MUTEX_INITIALIZERは単に{ 0 }
とかだと思います。

>>279
うわ。赤面しまくりです...。

ぶっちゃけUnixベースのライブラリをちょろっといじくってWin32に
移植しようと思っただけなのですが、こんなワナが待っていたとは
思ってもいませんでした。

282:デフォルトの名無しさん
07/03/04 10:24:41
下の例の場合変数iにvolatileは必要かどうか質問です。
lock, unlockがメモリバリアだから必要ないという認識なのですがつけている例も見ます。
>>261だとlockせずに読んでる箇所もあるので必要なのかもしれませんが、
この辺の基準ってどうされていますか?

int i;

thread_function() {
   mutex.lock()
   i = i + 1;
   mutex.unlock()
}


283:デフォルトの名無しさん
07/03/04 10:32:03
だれか
.NET Frameworkのメモリモデルとかに詳しい人おらんかね?


284:デフォルトの名無しさん
07/03/04 10:42:25
>>282
付けといた方がいいんじゃない?mutexのメモリバリアでcpuキャッシュの同期は取れても
スタックやレジスタに積まれたままだったら意味ないしね。

285:デフォルトの名無しさん
07/03/04 11:17:03
>>283
設計上はウィークメモリオーダリングということなので、OoOあり~の、コヒーレンシキャッシュは信用できね~のです。
今のところ実装上はx86系のWindows上ではストロングメモリオーダリングのみ。
Itaniumは構成によってウィークメモリオーダリングもある得るそうです。

286:デフォルトの名無しさん
07/03/04 11:51:52
ところが、CLR2.0では書き込みオーダは保証されてて、
今後もそうだと約束されてるらしい。

それはおいといて、よく理解できてないのが、
書き込みスレッドでメモリバリアを実行した場合、
読み込み前のメモリバリアは必要なのかどうか。

あるメモリ領域に書き込みしてメモリバリア実行、その後完了フラグセット。
別スレッドで完了フラグを確認してからメモリ領域を読み込みってときに、
完了フラグ確認後にメモリバリアは必要なのかどうか。
なんとなく読み込み順が保証されないから必要な気もするんだが、
.NETのメモリバリア命令はフルメモリバリアだから不要?ってのも見た。
.NETのメモリバリアは別プロセッサの読み込みキャッシュもクリアして
かつJITの最適化とかで先読みとかがおこらないなら大丈夫なんだと思うんだけど
この方面素人なのでいまいちよく分からない。


287:デフォルトの名無しさん
07/03/04 11:53:25
メモリバリアの説明には、このプロセッサ上でキャッシュをフラッシュするとかって説明になってんだよね…


288:デフォルトの名無しさん
07/03/04 13:04:32
Itaniumだと、そもそもout of orderしないですな。
命令の並べ替えや並列化はすべてコンパイラの仕事だ。

289:デフォルトの名無しさん
07/03/04 13:11:11
だからこそ その辺の事情は本来プログラムで意識したくないよな・・・

DCLの欠点なんて最たるものだし

290:デフォルトの名無しさん
07/03/04 17:17:43
>>282
メモリバリアだから必要ないという認識では、ちょっと違うね。
関数呼び出しをまたいでグローバル変数をキャッシュできないから
volatileが必要ないというのが本質。
変数をレジスタ等にキャッシュしていないからこそ、メモリバリアが有効になる。

仮にlockやunlockをインライン展開できるようなコードで実装できたとすると
while() { lock(); i = i + 1; unlock(); } はvolatileが無いと危険かもしれない。

291:デフォルトの名無しさん
07/03/04 19:41:48
>>290
それは本質じゃなく単なる実装の話だと思います。
たとえばmsvc++などは次の理由からそういう実装になっています。
現在のx86系WindowsはOoOはやっててもアプリからは見えないハード的な仕掛けになっていますし、
コヒーレントキャッシュもある前提なのでキャッシュによる不整合もありません。
x86はレジスタの数が少ないので関数呼び出しのタイミングで変数をメモリ上に書き出します。

たとえばpthreadのmutexではvolatileは不要とドキュメントにあります。
すべてのコンパイラがそうなってるかどうかは分かりませんが、少なくともスレッド系のライブラリと一体で
提供されている環境ではサポートされているはずです。

292:デフォルトの名無しさん
07/03/04 20:23:08
>>291
インライン展開できない関数を呼ぶ前は、x86であろうと無かろうと
非ローカル変数をキャッシュできないよ。
レジスタの数が問題なのではなく、非ローカルな変数は呼び出した先で
更新される可能性があるから。

293:デフォルトの名無しさん
07/03/04 21:03:48
あと、ローカル変数でも、アドレスを取って他の関数に渡している場合に
その前と後で変数の中身が変更される可能性は、コンパイラも考慮しているはず。
だから例えば>>255のlockや>>272のpにはvolatile不要なはず。
もちろん、>>255のinitializedには必要だけどね。

で、pthread_mutex_tも、アドレスを取って渡すのだからvolatile不要、
という考え方でも充分かもしれない。

ただし、アドレスを取って呼び出した関数から戻った後に
変数の中身が他のスレッドによって変更される可能性は考慮されないので
レジスタにキャッシュされるかもしれない。
それが問題になる可能性がある(コードで中身を参照している)ならば
volatileが必要になるね。

294:デフォルトの名無しさん
07/03/04 21:29:48
>>292
確かにそこは例えが悪かったので取り消します。
(PGOのような広域のインライン展開のことを考えていたのですが論旨に合わないようです)
言いたかったのは同期関数の呼び出しのタイミングで
偶然レジスタとメモリの同期が取られているという話ではなく、
メモリバリア実現の属性のひとつとして関数の呼び出し時にレジスタとメモリの同期が
とられるという仕組みが利用されてるということです。
だから、レジスタとメモリの同期以外にCPUキャッシュ間の同期やOoOの調整が必要ならば
その処理が同期関数に含まれていなければならないと考えているわけです。


295:デフォルトの名無しさん
07/03/05 18:53:41
         ____
       /      \
      /  ─    ─\
    /    (●)  (●) \馬鹿ばっか
    |       (__人__)    |
     \      ` ⌒´   /
    ノ           \
  /´               ヽ
 |    l              \
 ヽ    -一''''''"~~``'ー--、   -一'''''''ー-、.
  ヽ ____(⌒)(⌒)⌒) )  (⌒_(⌒)⌒)⌒))

296:デフォルトの名無しさん
07/03/05 22:57:17
volatile旋風スゴス

297:デフォルトの名無しさん
07/03/10 22:35:07
質問です。

while ( count > 1 ){
 pthread_cond_wait( &cond_t, &mutex );
}
この場合、条件変数と呼ばれるものはcountですか?
それともcond_tになるのでしょうか?
また、countのチェックにifは使ってはならない。と言われたのですが、
なぜだか解りません。
上記の部分と、
while (1){
 if( count > 1 ) pthread_cond_wait(ry);
}
は同じだと思うのですが・・・
よろしくお願いします

298:デフォルトの名無しさん
07/03/10 22:51:41
>>297

while (1)
{ 
  if( ! (count > 1) ) break;
  pthread_cond_wait(ry); 
} 
と同じだと思う。

299:デフォルトの名無しさん
07/03/10 23:04:21
>>298
そうでした。すんません

300:デフォルトの名無しさん
07/03/10 23:33:31
> 条件変数と呼ばれるものはcountですか?それともcond_tになるのでしょうか?
条件変数はcond_t。!(count>1)は述語。

> countのチェックにifは使ってはならない。と言われたのですが、
言った本人に聞けばいいと思う。いけないってことは無いと思う。
pthread_mutex_lock(&mutex);
while (!pred(ry))
 pthread_cond_wait(&cond, &mutex);
pthread_mutex_unlock(&mutex);
というのが定型パターンの予感はするんで、
その人にとって奇怪なコーディングするなという意味かもしれん。

301:デフォルトの名無しさん
07/03/11 08:33:14
ありがとうございます。
countは述語っていうのですか。知りませんでした。
>ifでんでん
後でもう一度聞いてみます。

302:デフォルトの名無しさん
07/03/11 11:25:05
でんでんってなんだ。云々(うんぬん)と言いたいのか、わざとボケてるのかどっちだ。

303:デフォルトの名無しさん
07/03/11 12:35:43
>>302
単なる2chのジャーゴンだから気にするな

304:デフォルトの名無しさん
07/03/11 14:17:43
countが述語なんじゃなくて
"count>1"が述語
countは単なる変数

305:301
07/03/11 15:38:51
>>304
"count>1"で、述語。ですか。解りました。
ありがとうございます。

>>でんでん
"うんぬん"で"云々"ですか。初めて知りました
ゆとり年代より一つ上なはずなんだけどゆとりでごめんなさい

306:300
07/03/11 15:43:08
ごめん。!(count>1)でなく、count>1だった。
301に幸あらんことを。

307:デフォルトの名無しさん
07/03/11 15:43:39
俺がかつて1日だけ流行らそうとしてばら撒いてたでんでんが意外な影響を。

308:デフォルトの名無しさん
07/03/11 16:04:43
「云々」を「でんでん」ってことは
「云」を「でん」と読んでるって事だよな。

俺、そもそも「云」という漢字、単独でどう読むか知らないのだが。

309:デフォルトの名無しさん
07/03/11 16:29:44
>>308
「ウン」でしょ。

310:デフォルトの名無しさん
07/03/11 16:37:38
伝が“でん”だからなあ

311:デフォルトの名無しさん
07/03/11 20:45:06
雲が「うん」と読まれることには頓着しないらしい。

312:デフォルトの名無しさん
07/03/11 22:22:20
ワンタン
雲呑

313:デフォルトの名無しさん
07/03/12 00:36:16
うーんぬんむーしむし、かーたつむりー

314:デフォルトの名無しさん
07/03/16 09:25:59
         ____
       /      \
      /  ─    ─\
    /    (●)  (●) \  「テラワロスwwwwwwwうぇうぇwwww」・・・・と
    |       (__人__)    | ________
     \      ` ⌒´   ,/ .| |          |
    ノ           \ | |          |
  /´           カタ.    | |          |
 |    l             カタ  | |          |
 ヽ    -一ー_~、⌒)^),-、   | |_________|
  ヽ ____,ノγ⌒ヽ)ニニ- ̄   | |  |       ____


315:デフォルトの名無しさん
07/03/20 00:12:35
ごめん書籍いいでしょっていわれてるけれど
マルチスレッドの勉強する本をおしえてほしいの

316:デフォルトの名無しさん
07/03/20 00:32:02
マルチスレッドについて本で得られるものは1%もない。
といっては見もふたもないので、もう少し具体的にマルチスレッドで何をしたいの?

OSは?マルチスレッドアプリ?APIがしりたい?それともカーネルの実装(はないよな)?

317:デフォルトの名無しさん
07/03/20 15:54:59
Unix 方面の人は「実践マルチスレッドプログラミング」
Win32の人は「Win32マルチスレッドプログラミング」

当り前のことが当たり前に書かれてるだけで、
別にいいも悪いもないけど。

このあたりに出てくるような概念、問題、手法については常識として理解した上で、
新しい手法やOS/CPU/言語毎のメモリモデルなどについての知識を深めると、
volatile 論議とかで無駄に遊べる。

318:デフォルトの名無しさん
07/03/20 23:15:04
>>315
Java使いなら↓は超オススメ。
URLリンク(www.amazon.co.jp)
邦訳版もあるよ。

319:デフォルトの名無しさん
07/03/21 00:27:18
>>317
素朴な疑問

> Unix 方面の人は「実践マルチスレッドプログラミング」
> Win32の人は「Win32マルチスレッドプログラミング」

この辺を読めば volatile 最強って言い切れるようになるんですか?


320:デフォルトの名無しさん
07/03/21 03:30:37
317をもう一度よく読んだほうがいいんじゃない?

321:デフォルトの名無しさん
07/03/21 04:34:08
自作自演の可能性

322:デフォルトの名無しさん
07/03/21 13:51:09
volatile厨を論破するのはそんなに簡単じゃないよ。

323:デフォルトの名無しさん
07/03/21 15:55:04
NG登録するだけだし

324:デフォルトの名無しさん
07/03/24 10:03:31
Win32の本ってオライリーのやつのことでいいの?

325:デフォルトの名無しさん
07/03/24 15:56:09
>>315
並行プログラミングの原理―プロセス間通信と同期への概念的アプローチ (単行本)

326:デフォルトの名無しさん
07/03/27 14:50:58
          ____
       / \  /\  キリッ
.     / (ー)  (ー)\
    /   ⌒(__人__)⌒ \ volatile厨を論破するのはそんなに簡単じゃないよ。
    |      |r┬-|    |  
     \     `ー'´   /
            ___
       /      \
クスクスッ /ノ  \   u. \ !?
    / (●)  (●)    \
    |   (__人__)    u.   |
     \ u.` ⌒´      /
         ____
       /      \!??
      /  u   ノ  \    クスクスッ
    /      u (●)  \
    |         (__人__)|
     \    u   .` ⌒/



327:デフォルトの名無しさん
07/03/27 22:33:12
Javaのsynchronizedとwaitとnotifyに関する質問なんだが

URLリンク(www.javaworld.jp)
ここの

class Buffer {
private int value;
private boolean isEmpty = true;
public synchronized void putValue(int v) {
while (!isEmpty) {
try {
wait();
} catch (InterruptedException e) { }
}
notifyAll();
isEmpty = false;
value = v;
}
public synchronized int getValue() {
while (isEmpty) {
try {
wait();
} catch (InterruptedException e) { }
}
notifyAll();
isEmpty = true;
return value;
}
}
これがどうして動くのか分からん。
あるスレッドがgetValueに入ってる間は、ほかのスレッドは
getValueにもputValueにも入れないんじゃないのか

328:デフォルトの名無しさん
07/03/27 22:34:13
すまんソースコードが見づらくなってしまった。
リンク先を見てくれ。

329:デフォルトの名無しさん
07/03/27 22:52:21
>>327
前のページで説明されてる。


330:デフォルトの名無しさん
07/03/27 22:53:08
URLリンク(sdc.sun.co.jp)()

の二段落目を理解できない無能?

331:デフォルトの名無しさん
07/03/27 23:05:42
すまんかった。
とんくす

332:デフォルトの名無しさん
07/03/28 08:53:09
          ____
       / \  /\  キリッ
.     / (ー)  (ー)\
    /   ⌒(__人__)⌒ \ の二段落目を理解できない無能?
    |      |r┬-|    |  
     \     `ー'´   /
            ___
       /      \
クスクスッ /ノ  \   u. \ !?
    / (●)  (●)    \
    |   (__人__)    u.   |
     \ u.` ⌒´      /
         ____
       /      \!??
      /  u   ノ  \    クスクスッ
    /      u (●)  \
    |         (__人__)|
     \    u   .` ⌒/



最新レス表示
レスジャンプ
類似スレ一覧
スレッドの検索
話題のニュース
おまかせリスト
オプション
しおりを挟む
スレッドに書込
スレッドの一覧
暇つぶし2ch