6 :
デフォルトの名無しさん :2008/07/09(水) 20:28:14
boost::threadを使っていて質問があります。 スレッドオブジェクトをスレッド処理完了後に自動消去したいのですが、 以下のやり方だとまずい気がします。定石みたいなものはないでしょうか? struct ThreadManager { boost::shared_ptr<Thread> th_; // 管理するスレッド bool thread_is_running(void) const { return th_!=0; } void start_thread(void) { if (thread_is_running()) return; th_.reset(new Thread(this)); boost::thread(boost::ref(*th_.get())); } // ※スレッド処理が終わったらth_を空にしたい void delete_thread(void) { thread.reset(); } }; struct Thread { ThreadManager* p_; Thread(ThreadManager* p) : p_(p) {} void operator()(void) { /* ... スレッド処理 ... */ p_->delete_thread(); } // スレッド処理終了後、ThreadManagerを通じて自分を消去 };
boost::shared_ptr<Thread> th(new Thread); boost::thread(boost::bind(&Thread::operator(), th));
8 :
6 :2008/07/09(水) 22:44:08
7が動くのは理解したのですが、ありがたみがいまいちわかりません。 この場合thはスレッド処理が完了したこと(つまりth.reset()を呼ぶタイミング)を どうやって知るのでしょうか。
いや…、どうやっても何もThreadのデストラクタが呼ばれるだろ。 ていうか何がしたいのさ? スレッド作ってあとは関知せずという無責任なマネをしたいのか、 メインスレッドと同期して何かをしたいのか。
10 :
6 :2008/07/09(水) 23:11:20
処理の種類に応じてThreadA、ThreadB、...(単一のThreadクラスを継承)を用意しています。 で、本体はThread*を1つ管理していて(p_とします)、 処理が必要になった時点でp_.reset(new ThreadA) のようにします。 その際に他のスレッドが処理中かどうかをp_!=0のように判定したいなと。
11 :
6 :2008/07/09(水) 23:14:32
ありゃ、なんか
>>10 は
>>6 の単なる繰り返しですね…。
何をしたいかというと、いくつかのマルチスレッド処理を
排他でとっかえひっかえ行いたいという感じでしょうか。
まあ、普通に thread pool 使えばいいんじゃね。
13 :
13 :2008/07/09(水) 23:36:47
教えてください。 A.cというファイルにグローバル定義で定義した volatile変数をB.cというファイルで参照したい場合、 volatile extern int hoge; とかでいいのでしょうか?
>>11 実行中のワーカスレッドが存在する場合にどういう選択肢があるのか
(終了を待ってから新しいスレッドを起動する/途中でも終わらせて新しいスレッドを起動する etc..)
によっても実装の仕方は変わってくると思うんだけど、どうだろう。
15 :
6 :2008/07/10(木) 04:26:36
>>14 今のところ、実行中のワーカスレッドが存在する場合には、
「別のスレッドを実行中だからスレッド終了まで待ってね」
と表示して何もせずにreturnという仕様です。
(
>>6 の方法で動いてたのですが、たまたま運が良かっただけですね)
>>13 B.cでその前にstatic volatile int hoge;と書いてなければOK
>>7 これって、スレッド終了より早くthがスコープ抜けても問題ないの?
>>6 がやりたいことはMFCのCWinThreadのbAutoDeleteでしょ。
>>16 shared_ptrでラップされてて、それを保持した
functorがスレッド終了時に破棄される。
そのタイミングでthの指すインスタンスも破棄される・・・・多分。
MFCは平気でdelete thisしてる。 ThreadManagerまで作ったのなら、()を直接呼び出すのでなくて ()を呼び出した後でメモリ解放するラッパーをサブスレッドで実行すればいい。 ついでにshared_ptrの操作前後で排他制御が必要。
タイムアウト監視中にシステム時刻が変更される可能性について 意識してない人が大杉な気がする。そういう脆弱なコードをいっぱい見てきた。 現実的な例として、ホストとの接続時に時刻の同期が要求される某FA分野プロトコルを 使ったシステムで、同時にハードとの通信のタイムアウトを監視してたら とても愉快なことが起こり得るわけだ。 つまり、pthread_cond_timedwaitの仕様は困るってこと。 非標準の相対時間によるwaitをサポートしないPthread環境で この問題を解決する方法が分からない、というかできないでFA?
放置!
ホスト時刻と端末時刻の差を管理すればいいだけじゃない
・時刻同期してから絶対時間に依存する処理を開始する ・時刻同期を徐々に(ntpd的に)行う
>>21 >>22 もしかしたら、俺がどうしてもUnixでシステムを動かす必要に迫られてると思って、
一生懸命解決策を考えてくれたんだろうか?だったらごめん。
Windows使ってます。
俺が知りたいのは、特定の仕様のシステムを実現する方法じゃなくて、
他のプログラムが何していようが、
ユーザが好き勝手に時刻を変更しようが、
現在からN秒以内に条件が成立しなければ、アウトという監視は本当にできないのかってこと。
Pthread標準の枠内で。
時刻をいじってるプログラムと密に連携したり同期とれるとか、
そんなこと当てにできないし、したくもない。
windowsでpthreadなの?よくわからんがTickCountじゃだめなのかな。
普通はハートビートを刻む液晶系のクロックと、カレンダ時計があって、 sleepだのwaitのタイムアウトの監視は前者、 カレンダ時計はcronのようなもっとスパンの長いスケジューラで使っていると思ったのだが、 pthread_cond_timedwaitはカレンダ時計を使ってるのかな。
pthread_cond_timedwaitは困ったことに絶対時間指定なんだ。 利用者にも実装者にも不評で pthread以外の同種のAPIで待機時間でなく絶対時間を 使っているのは見たことがない。
まあAPI仕様に無い以上無理なんだろう。勉強になりますた。 苦しい対処だが1秒タイムアウトをN回繰り返せば誤差1秒でタイムアウトできる、かな。 あとWindowsならスレッド生成だけpthread使って、同期はWin32 APIでするとか
情報小出し君にはレスしても無駄だと分かった
>>27 Windows で pthread ?
なんでそんなことしたいのかを書かないと、単なるバカにしか見えないよ。
あと、pthread_cond_timedwait がダメダメなら、setitimer でシグナル
もらうとかすればいいんじゃないのか?
Win32と言ったりpthreadと言ったり、答えようがない。 Win32には延長付のタイムアウトのAPIや時刻に影響しない経過時間を計測できるAPIがあるのに残念だったな。
32 :
27 :2008/07/12(土) 11:18:17
>>29 俺は
>>27 だが、
>>19 =
>>23 とは別人だ。
もともとの
>>19 がWindowsでpthreadのようだけど、企業でそういう指定があるから
だと推測した。それで「使ってるフリして回避する方法」として、同期だけWin32したら?
と言ってみた。
33 :
19 :2008/07/12(土) 13:00:21
>>19 =
>>23 だが、なんか混乱させてるな。
俺が現実に直面してる仕事なんかに関係なく、
このpthread_timedwaitの仕様どうなの?って話がしたかっただけ。
俺でも分かるような欠陥が本当にメジャーな標準規格にあるのか
疑問だったので、もしかしたら、今のPthreadの枠内で簡単に解決する方法があるのかと思った。
それも聞きたかったことの一つ。
Pthread本を見ると、絶対時刻が使われていることのメリットしか書かれてないけど、
俺としては、相対時刻でタイムアウト監視できるAPIの方がよほど必須のように思えたので。
tasksetの使い方教えてください。オプションとか…。 スレッド1→コア1 … スレッド4→コア4 みたいに割り当てたいのですが、 tasksetじゃできないですかね…? ちなみにlinuxでopenmpでやろうかと思っています
で、このスレとしてはPthreadではできないという結論になると。
>>26 C++ boostも絶対時間だったような。
>>34 そうしたい理由を先に言ったほうがいいよ
まさか
「割り当てられないとしたらその仕様どうなの?って話がしたかっただけ」
じゃないよな
>>35 最新版ではabstimeとreltime向けに別々の時間クラスが定義されて
timedwaitはオーバーロードされてる。
例によって、実装はテキトーに変換してるだけなので、
ネイティブに近い方のオーバーロードだけは信頼できるってかんじかな。
>>37 信頼できるかどうかはOS次第だと思う。
どんなラッパー仕様だろうと最終的にはOSのAPIを呼び出すことになるので
>>30 は当然のこと。もしPthreadのプログラムインターフェースしか提供されて
いないOSなら信頼はできない。
>>19 はPthreadの絶対時間指定によるデメリットを仕様欠陥と(あちこちで)指摘してるだけだろ。
一貫してるからいいんじゃね?
例がアレなので相手にされてないようだけど「システム時刻を修正されるとまずい」ってのは
事実で、時間が巻き戻らない前提ってのは無茶苦茶だ。SIベンダがBtoBで構築するシステムなら
ともかくフリーソフト作れねーぞ。
しかも理由が「絶対-相対の変換の足し算中にプリエンプションが発生すると待ち時間がずれる
から」ってのは納得できねー。タイムアウト時間にごく僅かな誤差が出ることに問題あるとは
思えないし、責任をアプリに押しつけただけなのは基盤として問題だろ
43 :
デフォルトの名無しさん :2008/07/13(日) 23:27:07
マルチスレッド対応にしたら デュアルコアのCPUを両方とも使って処理してくれるの?
>>43 普通はOSまかせ。
OSはコアをまんべんなく使おうとするから普通は両方使ってくれるが、
他のプログラムが1つのコアをめいいっぱい使ってたら、
同じコアに振られることもある。
サンクス
自演乙
47 :
デフォルトの名無しさん :2008/07/17(木) 02:11:04
自演乙厨w
void f() { static struct Hoge hoge; pthread_mutex_lock(); ///hogeにアクセス pthread_mutex_unlock(); } こんな感じのコードあってstaticだから安全だって譲らない K主任って糞がいます助けてください
Hogeがコンストラクタを持つの?
K主任も災難だな
>>48 少なくともそこで示されている記述だけじゃ
問題のあるソースだとは思えん。
pthread_mutex_lock()とかの引数に渡されているmutexが
非staticなauto変数とかだったらダメだけど。
hogeのアドレスを外部に漏らして、そっちはmutexなしでアクセスとか?
安全って理由が staticだから でmutexはあってもなくても関係ないって K主任が主張してあるのであれば、これはもうどうしようもない
ワロタ
つまりこういうこと?
>>48 って糞が粘着しています助けてください K主任
>>48 どんな危険があると考えてるのな?
hogeのポインタを外に出さない限りmutexはいらないと思うけど。
>>58 fが複数スレッドから呼ばれるとしたら、hogeをどうするのかによるね。
K主任が見てるようなので退散します・・・
strtokとstrtok_rの違いを考えろ
ネタを振った責任として
>>48 は、何が問題があると思うのかくらいは
説明して欲しいな。
>>60 hoge がstaticだから、hogeのコンストラクタが(あれば)起動時
一度だけ動くのみ。
だから排他部分の外で宣言されていても安全、ってことだろう。
とはいえstaticじゃ無かったとしても何か危険があるかというと
よくわからんから、staticだから安全ってのはなんか変な主張
という気がしなくもないな。
アドレスを外部に漏らしてなければ、この関数からしか アクセスできない。そこに排他がちゃんとかかってるか ら大丈夫だろ? って言うことだと思うが。
C99って言ってるから(
>>50 )コンストラクタはないんだが、
仮にc++だとすると
>>65 >hoge がstaticだから、hogeのコンストラクタが(あれば)起動時
>一度だけ動くのみ。
違うぞ。
static struct Hoge hoge; の行に到達したときに、
一度だけ実行される。
その「一度だけ」のフラグが排他されていないことがあるだろう、
というのが起こりうる問題。
仮にC++だとするとこうするべきってことですか? pthread_mutex_lock(); static struct Hoge hoge; ///hogeにアクセス pthread_mutex_unlock();
前スレ850くらいからその話題が出てるわけで
DCLでいいよ。
そこで-fthreadsafe-statics
そんな実装依存じゃK主任に笑われるぞ
ハードのことはよく分からないのですが、同じメモリアドレスに複数のコアが同時アクセスすると なにか問題が起こることはあるのでしょうか? 例えば整数型のグローバル変数aを作り、 スレッド1ではそれを読みこみ加算します。スレッド2ではそれを読み込み減算します。 シングルコアでは物理的に、本当の意味での同時アクセスはありえないので 意図した結果が得られないとしても、ハード的に不具合はないですよね。 仮にスレッド1ではreadのみ、スレッド2ではwriteのみだと何の問題もないはずです。 これがマルチコア環境だと、スレッド1がread, スレッド2がwriteのみだとしても 同メモリアドレスに各コアが本当の意味で同時アクセスしますよね。 こういうことはやってはいけないのでしょうか?
いや、同時アクセスしてもハード的な問題は起きない writeの結果がreadに反映されるかされないかの問題でしかない
>>73 それが同じCPU内の別のコアなら、キャッシュ管理かどっかで調停するから問題ない。
それが違うCPUのコアなら、メモリ管理かどっかで調停(ry
コア毎のキャッシュにヒットしなかったと仮定すると、 最終的に、競合するバスアクセスが発生するわけだが、 その時にはバスのアービタが調停する。
>>74-76 ありがとうございます。
調停(アービトレーション?)というのは調べても詳しくは分からなかったのですが、
同時アクセスするような状況で排他処理をしてくれるということでしょうか
ハード的な話なのでソフト的な排他処理とはちょっと違う希ガス。
ハード屋の無知はおいておくとして、信用するなよ。 マルチコアとシングルコアの違いは、スケジューラを動かす数が 違うのが一番大きい。あるスレッド(プロセス)は、基本的に1つの CPU上で動作する。 当然、複数のスレッド(プロセス)間の排他は必要だが、アプリ上 はたいして変わらない。マルチコアでは、アトミックな操作のための バスを占有するような命令が追加されているだけ。
>マルチコアとシングルコアの違いは、スケジューラを動かす数が 違うのが一番大きい。 誰もそんな話してないしw >あるスレッド(プロセス)は、基本的に1つの CPU上で動作する。 間違ってるし ロードバランスとか考え出すと頭が痛くなるが,まぁ Read-Write-lock みたいなことをやってると思っとけば
基本的にって言ってるから何でもあり。
て言うかある一瞬を言ってるのか、スレッドの一生を言ってるのかわからんから 間違ってるか判断できない。
突っ込み所が違うだろ。
>>73 に対して
>>74 〜
>>76 が問題ないって言ってるのにそれを否定してるんだぞ。
メモリの同時アクセスは複数プロセスでも起こるので、すべてのメモリアクセスは
明示的にバスの排他命令を使用する必要があるな。
>>79 の書き込みは、肝心なところがちゃんと書いてないから
正しいとか間違ってるとか言うことはできない。
まあ、>83 の書き込みも似たようなものだが。
86 :
デフォルトの名無しさん :2008/08/24(日) 23:25:42
RT-Linuxでマルチスレッドで組んでいます。
スケジューリングポリシーはSCHED_FIFOです。
pthread_condを使った排他を考えているのですが、
pthrad_cond_wait()を複数スレッドで呼び出した後に
pthrad_cond_broadcast()を呼び出した時の動き出すスレッドの
順番がスレッドの優先度順になっていません。
(ちなみにsunのページにはブロック解除の順番は不定と書いてありました。)
そもそもやりたい事が
ttp://www.hanecci.com/pukiwiki/index.php?Programming%2FMultiThreading の「リードライトロック」のような事なのですが、
優先度順に動き出させるようにするにはどうしたらいいですか?
よろしくおねがいします。
写生してえ。
だから、スケジューラの実装依存になるようなプログラムを組むなと なんど言ったらわかるのだ・・・。マイナーバージョンが変わっても、 挙動かわるぞ。
何のためのRT-Linux
>>86 pthread_cond_waitに入るときに、クリティカルセクション内で
現在待ちに入っているスレッドの優先度をメモっておいて、
pthread_cond_broadcastで起きたときに、クリティカルセクション内で
自分より高い優先度のスレッドが待ちに入っているなら、
何もせずに再びpthread_cond_waitに入る、じゃだめなのかな。
必ずその優先度の高いスレッドも起こされるはず・・・だと思う。
やばいタイミングとかあるか・・・な?
CPU稼働率落ちそうだな。
92 :
86 :2008/08/25(月) 22:44:47
解決した。
pthread_condとかつかわずに セマフォで普通に組めるのね。
ありがと。
>>87 うん
>>88 、89
そこでヒントがほしかった><
>>90 簡単な仕組みにしたいっすね。
>>91 ですね
簡単にCreateThreadできるようになるクラスとかないかな
boost::threadとか?
データ処理部分とHDDから読み込み&書き込み処理部分ってスレッド分けた方が効率上がると思うんですが、 HDDのIO部分自体は分けないで一つのスレッドでやった方が効率いいですよね? 2つの異なるHDDから読み込み&書き込みする場合はHDD毎にスレッド作った方が効率いいですよね? 間違ってたら指摘お願いしますm(_ _)m
>>95 ドライバはカーネルが動かす。従って、CPUが複数(或いは複数コア)あるなら
ユーザアプリとは並列に動ける。おまけに、ディスク自体にもバッファがあるから普通は余り意識しない。
まして一般的にディスクの方が圧倒的に遅いから、HDD毎にスレッドを作るなんて事はしない。
追記です。二つ目の質問は 「一つのHDDから複数のデータを読み書きするとき、データごとに別スレッドにはしないべきか」と言う意味です 宜しくお願いします
98 :
デフォルトの名無しさん :2008/09/09(火) 15:33:43
HDDは遅いから複数スレッドの方がいい HDD1が終わるまで待っている時間が無駄
早速回答ありがとうございます!
しかし
>>96 と
>>98 の言っていることが逆に見えて混乱しています
たとえカーネルが実際のIO等を行ってるとしても、読み込み終わるまでアプリは待機しますよね?
IO毎にスレッドを分ければその間CPUはアイドル状態にならずに効率が上がるかと思うのですが・・・
しかし、同じHDDで読み書きするデータごとにスレッドを分けるのは流石にやりすぎですよね^^;
>>99 >95はI/Oに限定した話じゃないの? I/Oしかやることがないならスレッド分けたって待つだけじゃん。
処理とI/Oを分けるかって話なら処理がI/Oに依存しないで済むなら分けておいたら? ってことになる。
一番初めに 「データ処理部分とHDDから読み込み&書き込み処理部分ってスレッド分けた方が」 って書いてあるだろ
>>100 ありがとうございます。処理とIOを分けたかったんです。
処理とIOは依存しないわけではないのですが、パイプライン式に順次並列処理しようかと思います。
読みながら処理しながら書くの? 読んでから処理してから書くの? 読みながら処理してから書くの?
こんな感じで実行予定です 以下同行は並列と見てください HDD1からDATA1読み込み HDD1からDATA2読み込み DATA1の処理 HDD1からDATA3読み込み DATA2の処理 HDD2にDATA1書き込み HDD1からDATA4読み込み DATA3の処理 HDD2にDATA2書き込み DATA4の処理 HDD2にDATA3書き込み HDD2にDATA4書き込み
マルチスレッドなんて使わずに非同期入出力で
106 :
デフォルトの名無しさん :2008/09/09(火) 18:30:45
非同期でOSまかせが速い、効率いいとはいえない。 データをまとめて出力するなどキャッシュを作った方が速い。 10Kを一万回やったら非同期でも時間かかる
読み込んだデータをクラスに展開しないといけないので、非同期読み込みだと メモリを最悪倍近く無駄に食うような気がしたのでこの方法がいいかと思ったのですが・・・ また、細切れに読み込んでも連続したデータであればキャッシュは効くと聞いたことが あるんですがそれも違うのでしょうか?
先読みに頼るぐらいならまとめて読め
>>107 win32なら、ファイルを開くときのオプションでキャッシュに連続の先読みを指示するオプションがある。
基本的にAPIの呼び出し回数を減らすのが速い
並列動作で効率を高めるため、最適な数のスレッドを生成したいのですが コア数を取得するAPIが見つからなくて困っています。API等では用意されていないのでしょうか
111 :
デフォルトの名無しさん :2008/09/12(金) 16:07:37
112 :
デフォルトの名無しさん :2008/09/12(金) 16:09:23
即レスさんくす! 無事取得できましたm(_ _)m
タスクマネージャのパフォーマンスグラフみたいに、 コア毎の負荷(使用率)を知りたいのですが、 簡単に取得する方法はありますか?
環境次第
マルチスレッド用の効率的なQueueを書いてください
状態変数の練習にはいいんじゃね
lock free queue
プライオリティキューを マルチスレッド化したいです
pthread_cond_wait()が遅くて しょりがおいつかないときって 大体方法何かないですか たすけて〜〜〜
どうやって遅いって調べたんだ つかwaitしてるようで実はポーリングになってるとかいうオチじゃなかろうな
私たちはマルチスレッドですか?
>>122 精子はマルチで卵子に向かいますが
卵子は基本的には一匹入ったらLockをかけるので
通常はシングルで動きます
でも、時々Lockに失敗して双子以上ができる場合があるので注意が必要です
マルチスレッドと言うより、 イベントドリブンというか、割り込み駆動な感じだな。
NMI最強
複数スレッドのプログラムへのCPUコアの対応としては
>>44 とのことですが、
コア数を設定できるソフトの場合、4コアCPUなので4コアを設定したとしても
OSが状況に応じてそれより少ないコアで処理させてり、というようなことが
起こってしまうのでしょうか?
>>127 ユーザープログラムを4コア設定にしようと
OSが割り当ててくれないかぎり無駄。
129 :
127 :2008/10/05(日) 12:10:42
>>128 なるほど・・・
いちおう4コアとか設定はできるものの、それは「4スレッド以上使うプログラムで実行しますよ」ということであって、
OSによりコアに手空きがあれば初めて実現することなんですね。
勉強になりました。
そうすると「このプログラムは2コアまで対応してるからCPUは2コアのものを購入」となるところを、余裕を見て
4コアCPUにしておく、という考え方が有効になるわけですね。
勉強になりました。
ありがとうございました。
有効ってまあ有効と言えば有効だけどあまり有効って感じじゃない。
裏で200も300もスレッド走ってなきゃ 2コアでも4コアでも指定したスレッド起こせるだろw その実装がスケール可能かつ性能どれだけ伸びるか考えろよw
余り細かい話になると、OSとCPUを特定しないと意味がなくなる気がするのだが。 因みにLinuxの場合、Gnomeが、ひいてはXが動いているとそれだけで1コア占有するくらいパフォーマンスが落ちることもあるので注意。 # 今時、それほど酷くないけどね。
>>132 それこそKernelとGnomeのバージョン言えって
話だけどな
134 :
デフォルトの名無しさん :2008/11/03(月) 14:53:14
pthread に、スレッドが pthread_cond_wait で待ち状態にあるかを判定する関数はありますか?
135 :
デフォルトの名無しさん :2008/11/03(月) 14:56:13
pthread に、スレッドが pthread_cond_wait で待ち状態にあるかを判定する関数はありますか?
2回書き込んでしまった。すんません。
大事なことだからしょうがない
大事なことだからしょうがない
して、待ち状態は判定できるんですか?
A.問い合わせる B.返事来る C.返事が甲なので甲とみなした処理をする んでB〜Cの間に乙になってて発狂する予感
>>135 wait状態を取得する関数があったとしても、現在もその状態である保障は無いね。
状態を取得した一瞬後には状態が変わってるかもしれんしな
pthread_cond_waitの引数のmutexを使えばできそうな。 pthread_mutex_trylockでmutexがロックできたらwait中。
トランザクションメモリの実装について くわし〜〜くかいた本ある?
>>144 「Transactional Memory」
くわし〜〜くはないがたくさんは載ってる
>>143 wakeupしたあとにCPUがまわってくるのを待ってる状態という場合もある
147 :
デフォルトの名無しさん :2008/11/09(日) 01:48:11
デバイスとの非同期処理の為に、別スレッドでポーリングしているんだが、 ポーリング関数内で、select -> read の処理を丸ごとロックしてる。 書き込みは メインスレッド内でロックして write 。 一応動いてるんだけど、どうも自信がない。 間違って select なりmutex なりを使っている気がする。 こういう類いの処理ってどういう本読めばいいのかな。 何かアドバイスください。
それだと、ポーリング用スレッドがselect+readでロックしている間、 メインスレッドがロックを獲得できない(writeできない)気がするがどうか。 select実行中のロックは不要だろう。 ただselect用のFD_SET作成中はロックがいる気がする。 みたいな。
>>147 情報が少なくてよくわからないけど、とどのつまり、何のために
ロックしなくちゃいけないかってこと次第
read と write が同時に発行できるならロック不要だし、
同時に出来ないなら、そのルールに合わせてロック入れる。
あと、多分、 select は不要なんじゃないかね
150 :
デフォルトの名無しさん :2008/11/09(日) 16:46:16
関数型言語だと具体的にどういう風にマルチスレッドに最適なの? 去年あたりからErlangとかScalaとかHaskellとかが話題になってて気になる。 全ての関数がワーカスレッドベースになるとかそんなとんでも話じゃないよね?
STM難しい やる夫助けてくれ
153 :
デフォルトの名無しさん :2008/11/09(日) 20:00:16
すみません。言語としてWinAPI(C言語)、C#、Javaを覚えたのですが(どれもGUIやファイル操作、DB接続ができる程度のレベルです。あとネットワークも少々) スレッドプログラムを次はマスターしたいのですが、どの言語でスレッドを学ぶのが一番いいですか? ひとつ覚えたら残りの言語も覚えたいと思っていますので、とっかかりに一番いいのをおしえてください。 よろしくお願いします。
Java
>>153 どれでもいいよ。そんな取り立てて挙げるほど大層なもんじゃない。
156 :
デフォルトの名無しさん :2008/11/09(日) 20:52:34
まぁJavaかC#だな。C言語でやるとLockが面倒だし
だね。 スレッドに絡む部分、概念の学習に専念できるという意味でも、 JavaかC#辺りがやりやすいと思う。
良書が揃ってるのはJavaだからJavaにしとけばいいと思うよ
159 :
153 :2008/11/09(日) 23:06:46
みなさんどうもありがとうございます。
>>156 さん、WinAPIでやるとちょっと面倒なんですね。
なるべく単純な概念だけを覚えたいので、C#かJavaにしようとおもいます。
でも、
>>154 サン以降全員Javaが候補に入ってるのでJavaにしようとおもいます。
いまから、本屋にいって立ち読みしてきたいとおみます。みなさん、ありがとうございました。
念願のスレッドプログラムの第一歩を踏み込めそうです。
ところでおまいらhyukiの 『Java言語で学ぶデザインパターン入門マルチスレッド編』 っておすすめでしょうか?
Java固有の話とそうでない話を見分けるつもりで読むといいよ
並行プログラムの本がある、おすすめ。
>>160 入門書としてはベスト。それ卒業したら「Java並行処理プログラミング」
JavaってマルチCPUなりコアなりの環境でもシングルCPUしか使えない と認識してるけどあってる?
あってる グリーンスレッドっていう環境にやさしいスレッド方式があって、 デフォルトはそれになってる
グリーンスレッドなのはjavaの最初の版だけだったと記憶してるけど、 今でも切り替えられたっけ?
>>165 十年前から乙。
>>166 無理。グリーンスレッドとネイティブスレッドの切り替えがあるのはClassicVMで、HotspotVMはネイティブスレッドのみ。
で、ClassicVMはJava1.4あたりで切られたようだ。
1.2 ぐらいまではずっとグリーンスレッドだった。 最初の版だけなんてことはない。
WroxのProfessional Multicore Programming ってCore2とかAMDのCPUのことも書いてあるんだな
>>170 Intelのパフォーマンスライブラリに期待しよう
>>170 元気なプロセスをいっぱい動かせば良いだけのような気もする。
同じアドレスに一斉に読み書きするとか 同じロックを一斉に取得、解放するとか そういうループをブン回して どうなるか観察したい
>>170 スレッドを192個作る。
各スレッドのaffinityを設定して、CPUに貼り付ける。
特定のスレッドのセットをビジーループにして、タスクマネージャに文字を出す。
>>175 > 特定のスレッドのセットをビジーループにして、タスクマネージャに文字を出す。
ビルのイルミネーションみたいでいいね!
winで1プロセスに64コア以上ってどうやるんだっけか
>>177 >Windows 7/Windows Server 2008 R2 では 64 論理 CPU をひとつの "グループ" と定義し,
>プロセスは初期状態で "グループ" のどれかに束縛されている(どのグループに属するかはラウンドロビンで決定される).
>そして,新しく定義された API で明示的に許可を与えない限り,プロセス内のスレッドは
>所属 "グループ" の CPU でのみ実行される.
>つまり,新しい CPU グループ制御 API を使用しない限り,ひとつのプロセスは高々 64 個の
>プロセッサしか活用しない.
ttp://d.hatena.ne.jp/NyaRuRu/20081107/p1
窓7が主流になる頃には64コアCPUとか出てるって事? 凄いな
マルチCPU
8コア*8CPUでやっと64 4CPUのマザーは見たことあるけど…
ブレードにすればよかろう。
コンシューマ向けの話じゃないのか
て言うか、ブレードってブレード毎にOSが載ると思うが。 8ブレードとかを1つのOSで制御できる奴なんてあるのか?
>>185 これ買おうかな
やっぱ自宅警備にはこれくらいのマシンがないとな
187 :
デフォルトの名無しさん :2008/11/20(木) 17:32:02
int i; for( i=0; i<10; i++ ) { h = CreateThread ( NULL, 0, (LPTHREAD_START_ROUTINE)DoIt, NULL, 0, &id ); } void WINAPI DoIt() { // ここでいろいろ } のようにして同じ関数を複数のスレッドで行いたいのですが ここでいろいろのところに制御がいかず すぐにスレッドが終了するのですが 同じ関数をスレッドで実行することはできないのでしょうか? WindowsXP C/C++ Win32API
>>187 まず先に突っ込んでおくが、LPTHREAD_START_ROUTINEと
合わない関数をキャストで無理矢理渡すな。
DoIt()がLPTHREAD_START_ROUTINEに適合する関数なら
キャストなんて必要ない。
すぐにスレッドが終了するってのは、どうやって確認した?
CreateThreadを呼んだメインスレッドは、各スレッドが仕事を
終えるまで待機している?
そもそもDoIt()がすぐに終了する内容じゃないの?
>>188 すいません
処理の流れがつかめてませんでした
解決しました
便乗して質問ですが WindowsXP Home Edition にて作成するスレッド数の上限はありますか?
マルチもいいけど 実行ファイルが自分で空いてるCPU選ぶようにしたい Windows側でプロセス作成時に勝手にやってるとありがたい
意味がわからん。 スレッドはあいているCPUでしか実行出来ないし。 ひょっとして、自分のプロセス専用にCPUが 割り振られて欲しいって話か?
194 :
デフォルトの名無しさん :2008/11/21(金) 10:58:32
Sleep関数について質問ですが MSDNによると VOID Sleep( DWORD dwMilliseconds // 中断の時間 ); とありますが マイナスの値を代入した時の挙動はどうなるのでしょうか? 実際ためしてみたのですが、永遠制御が返ってきません
DWORDは符号なしの型だからマイナス値を取れないと思うが
VC6はゴミということで
まぁそりゃ暗黙に型変換されてるんだろう 警告なしにそういった型変換をするのはCの悪いところ というか警告レベルを上げましょう
マルチスレッド対応で60FPSを維持する方法ってどうやるんですか?
ぇ?w 垂直同期とか
えいえんは、あるよ 49.7日ぐらい
Cはゴミということで
>196 まず警告レベルを上げろ。
>>205 警告レベル4にしたら
STLのライブラリのソースでwarnningが・・・
MS君・・・
STL で warning はよくあること。 まあ気にすんな。 鬱陶しければ #pragma warning(disable: XXXX) で消して 後で #pragma warning(default: XXXX) で復活させれば良い。
CreateThreadでクラスのメンバ関数って渡せますか?
なんとなく自己解決しました
test
>>201 INFINITE = 0xFFFFFFFF = (DWORD)-1
P2Pや分散メモリに適した高速 ロックってどんなのがあるのですか?
とりあえず知ってる言葉を並べてみました。
>>213 高速なパッセージならやっぱ3大ギタリスト、とくにベックじゃね?
ルカサーも捨てがたいが
若いのは知らん
やっぱりクリティカルなセクションをアトミックに相互排他する場合 レスポンスタイムが長いメモリをダイレクトにアクセスするのは非効率だから トランザクショナルメモリみたいな遅延する仕組みがマストニードじゃないですかね
日本語でおk
やっぱり際どい領域を原子的に相互排他する場合 反応時間が長い記憶装置を直接読み書きするのは非効率だから トランザクショナルメモリみたいな遅延する仕組みがどうしても必要じゃないですかね トランザクショナルメモリだけはどうにもならんかった。
「処理単位記憶装置」かな?
都覧公国量産型六番書鳴記憶
ザクメモリってどうやってつくるの? アルゴリズム全然解らん
弱そうなメモリだな
トラングフショナルメモリ
トランザクショナルメモリって どんなアルゴリズムなのですかね? 何処探してもみつからない
ロックフリーあたりで調べればいいと思う でもコストが大きい気がするのでリードライトロック程度で十分かと
リードライトロックの中にもフェアかフェアじゃないかで変わるけどね。 オブジェクト指向はハードウェアの都合までは吸収してくれんよなぁ。 マルチスレッドのデザパタ見ててそう思う。
排他制御書き込みって pthread_rwlockで実現できますか?
素直にmutexつかっとけ 読み書き両方な
>228 排他制御書き込み実現しようとすると pthread_mutexでは、try_lockを全mutex分 毎回ぶん回すってことでおkなのかな? この辺の定石ってよくわからん
mutexが複数あるの? どういう排他制御をしたいのかわからん
スレッド2000個作って 画像データダウンロードするやつ作ったんだけど スレッドが全部同時に動作しないんだ どこがいけないんだ?
当てずっぽうだけどサーバが2000接続も同時に処理できないんじゃね 1個ずつ順番に処理して残りは待たされてるとか
そもそも2000スレッドが同時に動くはずがない。
1000コア*2(HT)ですね もしそんなのがあったとしても現状Linuxしか動かせない
「全部同時に」ってのがどの程度の同時性を指してるんでしょうね
Sunのやつなら動くと思うよ
どの程度とかの精度の問題ではないんですよ 動けばいいだけのレベルなんですけど for ループ内で約2000 個のスレッド作るんで、 タイミング的にはほぼ同時な気がしますが OSにもよるかもしれませんが、 そうそう10秒以上も差が出るとは思えないんで 精度は10秒以内くらいの超おおざっぱでいいですけど 動かないんですよ ちなみにCUI コマンドプロンプトで多数のスレッドから printf されるとやはり多重に出力され hogehogehogehoge が hohohogegegehoge になったりするんでしょうか?
環境は? win32じゃなさそうだが
Erlangなら60000スレッドぐらい起せるよ
>>237 標準出力はバッファリングされるので、混ざる場合はバッファサイズずつ混ざる。
>237のように1バイトずつ混ざることはない。
おれも1万個ぐらい動かしてるけど別に問題ないな。 機密事項だから環境は書けないが。
>スレッド2000個作って画像データダウンロードする あほのすることだな
>>244 ネットワークモニタの使用率が25%超えたことないんで
限界までいどみたかったとです
>>245 自分で対向サーバを用意すれば簡単だよ。
スレッドって関係あるん?
2000個もスレッド作ってりゃオーバーヘッド大きすぎてそりゃ限界までいかんわな。 っていうかそもそもネットワークモニタって実効速度の%出してくれるんだっけ??
>>249 タスクマネージャにあるよ
OSの限界ギリギリまで性能を出そうとしたのに
なんてOSだ・・・
馬鹿は巣にお帰りください。
だからなんでスレッドにすると帯域使用量が上がるんだっけ? でっかいファイル一つを read するのと、スレッド2000個で read するので 差が出る理由はなに?
ネットワークの話じゃなかったのか。
ああ、そういうことね 1スレッドひとつにつき1つの画像をダウンロードするプログラムを組んだ このスレッドを2000個同時に実行したけど 2000個同時(プログラム的には)には動作してくれなかった ということ
だから、2000ポート空けて待つような対向サーバを自前で用意しろって。
>>250 だからさあ、例えばギガビットイーサだったら100%って1Gbpsじゃないの?
実効速度250Mps出てても25%だぜ?
バス速度的に実際1Gbpsなんて無理 100Base-TXで考えなさい
FPGAのNICなら1Gっていったら1G出ますが?
うん 馬鹿は帰れ
>>254 そもそも、シングルコア、1スレッドあたりのタイムスライスを10msとすると、
1周するのに単純計算で10ms×2,000=20,000ms=20秒だ。実際には10msよりも
もっと長いのが普通(※1)だし、スレッド切り替えにもコストがかかる(※2)し、
マルチコアとしてもコア数分の1にしかならない上に、コア間の調停にも
やっぱりコストがかかる(※3)。
あと、ネットワークの実効速度についても、デカいパケットが順番に流れる
なら、かなり帯域上限に近付けることができるが、細かいパケットが非同期に
衝突しまくりながら流れるようだと、いいとこ1/3くらいしか出ない。
ぶっちゃけ、アプローチが間違ってるとしか思えん。
※1:ぐぐってみたところ、Windowsについてはこんなんが引っかかった。
ttp://itpro.nikkeibp.co.jp/article/COLUMN/20080602/305755/?ST=develop&P=3 もっと良い資料やUNIXについての言及があれば教えてくれ。
※2:レジスタ等のコンテキスト情報を全部保存してパイプラインを捨てて
他スレッドのコンテキストを読み込む。キャッシュから溢れてたら最悪
メインメモリまで取りに行くハメになるぞ。
※3:各コアが互いに読み書きできるレイヤまでデータが届く必要があるため。
たしか一般に、CPUサイクルで見て、 スレッド作成が数万〜10万サイクル(ひょっとすると数十万〜だったかも)、 コンテキストスイッチが数千〜1万サイクル とか見た気がする。
おっと、スレッドに関わるオーバーヘッドの話ね。
>>262 >コンテキストスイッチが数千〜1万サイクル
今時LinuxでもO(1)スケジューラなわけだが。
そりゃ的外れなレスなこって
ワロタ
WindowsとかLinuxとか・・・ そんな貧乏臭いOSの話ばっかでワロタ
そうですか
アセンブラ級はついていけn
何十万ものスレッドをサポートするようなシステムもあるんだよね? どういう構造になってんだろ 根本的に考え方からちがうのかな?
>>270 カーネルスレッドは使わない(ユーザスレッドでやる)、か、そういうスレッドを
サポートしたカーネルでないと無理。普通のUnixの普通のカーネル(含むLinux)
とかだと無理。
OSはWindowsXPなんですよ
で、ソースですが
for( int i=0; i<2000; i++ )
{
_beginthred( DoIt, 0, NULL );
}
void DoIt( void * )
{
DownloadURL( URL, filename );
_endthread();
}
ってな感じですけど
ほとんど同時時間にスレッドを起動させてるのですが、
タイムスライスが各スレッドに割り当てられないのでしょうかね?
それともやっぱり
>>232 さんの言っているように
サーバー側が延滞処理をほどこしているんでしょうかね?
問い合わせたくてもあまり進んで聞けるようなことではないので
>272 スタック用の仮想メモリが足りなくなってない? あるいは、その呼んでいるDownloadURLが STAみたいな実装とかw >261 IOが支配的なスレッドで、タイムスライスの意味なんか ほとんどないとおもうけど。
同一サーバにHTTPコネクションを2000張ろうとしていたオチと予想
Irvineとかで試してみればどうかな
>>273 仮想メモリなのに足りなくなるとは、これいかに。
2000個のスレッドでスタックだけで仮想メモリ使い切るだろWin32なら。
いくらIOバウンドだって普通2000はやりすぎ。 普通はせいぜい100までだろう、CPU数にもよるがそれでも多いくらいだろう。 だいたい2000個の各ファイルのサイズはどのくらいで、 単体での転送速度はどのくらいなんだ。 ってダウンロードが2個までしか同時に動いてなかったりしてなw あとサーバ側も普通は当然そんなに同時処理できない キューに入って順番に処理されるだけ。
>>278 > 2000個のスレッドでスタックだけで仮想メモリ使い切るだろWin32なら。
相変わらず意味不明。
俺がワーカスレッドをプールする場合は、 特に深く考えずに単にコア数の倍だけ用意しとく。 IOブロックで動けるようになった他のスレッドもIOでブロックされるだけだしね。
>277,280 正確には仮想メモリ空間。 Win32では、ふつー、プロセス毎に、ユーザ空間として 使用可能なのは、下位から7fffffffあたりまでで、2GB。 だいたい、ポインタが32bitであることの限界とみていい。 で、Win32のスレッドは、1つあたり、規定では1MBの スタックを仮想メモリ空間に確保する。他にもDLLとかの コード領域も同じ2GBの空間を使うわけで。
>>282 仮想メモリというのはプロセス毎にあってだな・・・
>>281 だったらコア数の2倍はちょっと少なくない?
まあIOってもネットワークなどの場合で、
もちろん少ない投入数で帯域使いきれるような場合や
同一サーバにつなぐような場合は別だが。
Win32(笑)
ネイティブなプロセスやスレッドで並列性増やす方法は全然スケールしないから 軽量プロセス/スレッドが流行るんだろ Erlangのような言語は言語のレベルでそういうものをサポートしている 目的がI/O多重化なら昔ながらのselect系のシステムコールが使える WindowsならIOCP Javaは1.4以降でnioという形でそれをサポートしてるし Cならlighttpdで使われているlibeventのようなものがある それはそうと、Windows XPあたりだと、デフォではTCPの同時接続数が10だかに 制限されているはずだが
>>289 「どれ」についてのソースなのか分からんが、
最後のものについてなら、そのまんま
Windows XP 同時接続数
でぐぐればいくらでも情報が手に入るだろ
UDPは制限あるの?
知らん UDPにはconnectionという概念がないから、多分無いんじゃないかとは思うが 自分で調べたらどうだ
いやです ありがとうございました
ググってみたが、XPのSP2から1秒間につき10コネクションという 制限がついたらしい。 時間をあければ万単位までいけるみたいだが。
Windows XP Professional の場合、ネットワーク経由で同時に接続することができるコンピュータの最大数は 10 です。 とありますが、 メッセンジャーに繋げてますが この状態だと最大数は9になるのでしょうか?
制限解除するパッチもあるよ。公式じゃないけど。
もう少し詳しく調べてみた。 同時最大接続数が10に制限されるのは、listenする側の制限。 ようするに自分がサーバになる場合。 外向きの接続に関する制限は、half-open connectionが 1秒間に10個までに制限されている。(SP2から) half-open connectionは相手がacceptしてない接続のこと。 外向きの接続数に関しては、能力的な限界以外に制限は無さそう。 ただし1スレッドにつき64ソケットの上限有り。(回避は可能)
>>297 え?内向きの制限はもともとサーバー系でない奴にはついていて、
XP SP2以降のは、外向きの制限だろ?
299 :
298 :2008/12/09(火) 13:15:20
要は、listenじゃなくて、外に貼りに行くコネクション数に制限がついたってことな
>>298-299 そういう制限は見当たらなかった。
日本語の非プログラマ系のブログでそう書いてるところはあるが、勘違いだろう。
実際にセッションモニタ見てると、10なんて余裕で超えてるし。
>>300 は?
Event ID 4226でぐぐれよ
秒間の「外向きの」同時接続試行回数に関する制限で、
非公式のtcpip.sysに対するパッチも出ているから
P2Pとかやると直ぐでるからわかる
ああ、論点のずれが分かった 10個以上のTCP/IPのコネクションが維持できないって制限じゃないだろ 秒間に10個以上SYNパケット(TCPの最初のハンドシェイクで使う)を 投げないようにしているだけのはずだ 要するにスレッド沢山つくって並列でダウンロードさせようとしたところで 10個目以降ではconnect()呼んだ時点で制限にひっかかり、少なくとも他の ハンドシェイクが完了するまでは待たされるってこった
ちゃんと297でhalf-open connectionと書いたんだが。 それを否定されたら、同時セッション数としか読み取れないよ。
そうだな、よく読んでなかった すまん
クライアントでどこまでスケールさせる気だ。
googleのクローラでね?w
シングルスレッドでダウンロードするとうまくいくのですが マルチスレッドでダウンロードするとエラーが返ってきて GetLastError() で戻り値を調べても 0 で何が原因か分からないのですが どなたか分かりませんか? WinXP です
309 :
308 :2008/12/10(水) 17:29:32
マルチスレッドといっても、デバックの為、スレッドはひとつなので 競合などはおきないように設計しているのですけど、うまくいかないのです
さすがにそれだけで答えろって言われても、俺には無理だな。 GetLastErrorを呼ぶスレッドは合ってるの?
ダウンロードはどのAPIを使っているの?
>>311 ググってもでないのよねフフフフフフフフフ
313 :
308 :2008/12/10(水) 19:19:36
>>311 WinInet
InternetOpen
以外のAPIだけとは言っておく
>>311 とあるライブラリなんです
何かはいえませんが
俺は原因わかったよ ここには書けないけど
内々に連絡しておいた。
Debug版を納品とかフフフフフフフフフフフフフフフフフフフフフ フフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフ
ソースも示さずデバッグ依頼とな。
>>318 お主もなかなかのフフフフフフ
でもユーザー名ばれるのよねフフフフフフフッフフフフフフッフ
夜中にひとりでデバッグしてる時に フフフフフフフフフフフフフフフフフフフフフフフフフ とか feeefeee feeefeee feeefeee feeefeee とか見ると鳥肌が立ちそうになる・・・
323 :
デフォルトの名無しさん :2008/12/11(木) 14:11:44
POSIXスレッドでmutexロックでのデッドロックの回避法教えてください
馬鹿どもにマルチスレッドを走らせるな
>>323 2個以上のmutexを同時にロックしないというルールを徹底させるのが一番簡単かと
走る〜♪ 走る〜♪ スレッドーたーちー♪
馬鹿ですいません><
_beginthread( multi, 0, data ); >はわわわわ〜 >はわわわわ〜 >はわわわわ〜 >はわわわわ〜 >はわわわわ〜 >はわわわわ〜 >はわわわわ〜 >はわわわわ〜 >はわわわわ〜 >はわわわわ〜 >はわわわわ〜 >はわわわわ〜 >はわわわわ〜 >はわわわわ〜 >はわわわわ〜 >はわわわわ〜 >はわわわわ〜 >はわわわわ〜 >はわわわわ〜
APIの問題ではなかったようだ 設計の問題だったようだ これは普通気づかない
Critical! Criticalなのぉ〜 Criticalな処理をしていなかったのぉ〜 んぼおおおおおおおおおおおおおおおお
馬鹿はマルチスレッドやっちゃだめだよ。 死んだじっちゃんの口癖だった。 馬鹿って言うのは思考力が著しく劣る人なんだけど、 具体的に例をあげれば、自分で調べて答えを見つけられない人の事なんだ。
だ〜か〜らぁ〜 ぐぐってもgooで聞いてもダメなのぉぉぉぉ〜〜〜〜
デッドロック 予防 とか、デッドロック 回避 とかで検索して、端から見ていってみ。
1スレッド 2スレッド 3スレッド 4スレッド 5スレッド 全部ためしたののですが1スレッドが一番早かったです どうしてでしょうか?
よくあることです。
何を試したんだよ
キアイ
338 :
デフォルトの名無しさん :2008/12/13(土) 19:48:33
あるスレッドで処理した結果をメインスレッドに渡したいのだがどうすればいい? _beginthreadexの第3引数に結果用のポインタを渡せばいいのか
典型的にはソウデスナ 処理してほしい内容と 処理結果の格納場所を 与えるのがよろしいかと思いますダ
>>334 マルチスレッド化して速くなるかどうかは状況による。
その状況がわからなきゃ、何とも言えない。
>>338 グローバル変数でいいよ
メモリ空間を共有してるのがスレッドのメリットなんだし
…
volatile最強
>>388 俺はそういう場合スレッドセーフなスマートポインタ使うな
スレッドにデータを渡す前に参照カウント増やしといて
スレッド側では使い終わったら解放
メインスレッドは結果が必要なくなればスレッドが終了していなくてもデータを解放できる
クラスにしてthis渡してるな class tiny_thread abstract { protected: HANDLE m_hthread; unsigned m_id; : いろいろメンバー private: static unsigned WINAPI thread_start(void *o) { tiny_thread *tt = (tiny_thread *) o; return tt->run(); } public: bool start() { m_hthread = (HANDLE) _beginthreadex(NULL, 0, thread_start, this, 0, &m_id); return m_hthread != 0; } virtual int run() = 0; };
・メインスレッドが必ずサブスレッドより長生きするようにする。
メインがサブをjoinなり必要に応じて中断するなりする。
・結果格納場所のポインタやコールバック関数のアドレスをサブに渡す。
メインがUIスレッドの場合、サブからPostThreadMessageした方が楽かも知れない
・通信用メモリの解放責任をメイン側と決めておく
>>345 みたいなサブスレッドだけ生き続ける設計は個人的に(GCの無い言語では)嫌だ
これらが難しいと思うなら
>>342 だね。カッコ悪いけど確実かな
PostThreadMessageは取りこぼしが発生するので使っちゃいけません。 PostMessageを代わりに使おう。
ところで、ファイバーってどうなん。 アイドル状態のスレッドでパカパカやって動かすとか スケジュール処理なワーカスレッド代わりとかしか思い浮かばん。 漏れは、スレッドの処理は概ね、待ち処理とか先行処理なので、 あまり使い方が思い浮かばない。
>>351 ファイバーは移植のためにあるようなもので
新規プロジェクトで使う価値は無に等しい。
>>352 短絡杉
プリエンプティブであることは必ずしも望ましいことじゃない。
ゲームではファイバーが好まれる。
Larrabeeでもシェーダはファイバーで実装されるそうだ。
マルチコアでハイパフォーマンスだすためにファイーバーは重要。
自分でコンテキストスイッチとかめんどくせぇぇぇ
ちまちま排他処理すんのめんどくせぇぇぇ
>>352 、353
マルチスレッドで複数の関数叩くのと、ファイバーを複数キックするのの違いってやっぱ、
同期処理が不必要(他のスレッドでキック中のファイバーは自動的に同期される?)だとか
スタックの制限(ファイバーキックされた段階でスタック指定できる)ですか?
いえ、無論色んな意味合いで違うことは判るけど。
357 :
デフォルトの名無しさん :2008/12/20(土) 16:20:24
int result = write( buf, size ); if( result == -1 && errno == EAGAIN ) SwitchNextCoroutine(); I/Oイベントドリブンなスケジューラをみたことある。↑みたいなの。 あとは同期が要らないってのが素晴らしい。
それは歪でいまいちだね〜 まずコルーチンがあって それにスケジューラを足してファイバー イテレータ風に味付けしてジェネレータ(C#のyieldのことね) という階層があるべき姿だと思うな。
64CPU環境でスレッドを256本生成したときに struct data[2000]; なんてあって、dataの個々の要素を排他的にアクセスしたい場合 pthread_mutex以外に使えそうな手段ってありますか? CASってどうやって使うのかよくわからんし助けて
pthread_mutexでマズい理由は?
>>361 2000個もpthread_mutex_tって用意して使えるのですかね?
発想が変?
mutexを2000個作って問題ないと思うよ。 自分だったら、struct data[200] 全体に対して1個のmutexにして、それ でパフォーマンスの問題が出たらそのときに対処を考える。 reader-writerロックが使えれば使う。
訂正。 > 自分だったら、struct data[200] 全体に対して1個のmutexにして、それ struct data[2000] ね。
>>362 pthread_mutex_t はただのデータだから、何個作っても
そのプロセスのメモリ以外の資源は使わない
連結リストをCAS使って実装するときのお手本ってありますか?
双方向は無いのか........................
双方向でできると思ってんのかっ
rw_lockAPIが存在する環境で 同じrw_lock変数を以下のような構造で使うのって 問題ないでしょうか。 func() { rw_lock(read) if 条件{ rw_lock(write) rw_unlock(write) } rw_unlock(read) }
オレオレOSのオレオレrw_lock APIなら大丈夫だけど?
実装次第だが、普通に考えるとデッドロックするな
r_lock 確保してるんだから if の中の w_lock が取れないだろjk
なぜrでロックしないといけないのかわからんけど、条件に関わるのか?
>>375 このパターン自体は典型的なケースだろ
APIによっては、ReaderとWriterの他に「Writerに変更可能なReader」が用意されていることもある
WindowsでCreateThread中Cランタイムに含まれる関数を使うとリークを起こすとありますが、 普段からCreateThreadは使わずbeginthreadを使ったほうがいいんですか? 完全にCランタイム使わずってのも面倒だし、内部で使ってる関数があるかもしれない そういうことまで考えてあえてCreateThreadを使うメリットはあるのでしょうか?
軽い
ない
_beginthreadexでおk
ないな
pthreadでmutexで 再起ロックする場合と 依存関係をハッキリさせてスレッドIDとFAST_MUTEXで判別 どっちが高速ですか?
後者。 以前計測したことがある。 ただし、依存関係の洗い出し作業がとても大変だった。 デッドロックに直結するから、とても気をつけないといけない。 要求性能がシビアだったから後者で仕事のためにやったけど、趣味ならば前者をお薦めする。 排他制御がボトルネックになるようなら、前者で実装すればいい。 俺の場合は、本当に特殊で制限が厳しかったから前者でやっただけ。
×排他制御がボトルネックになるようなら、前者で実装すればいい。 ○排他制御がボトルネックになってから、後者で実装すればいい。
FAST_MUTEXって何?
386 :
383 :2009/02/01(日) 16:18:24
色々ぐだぐだだな。 お家で寝たいよ。
struct hoge{ int var pthread_mutex_t m; struct hoge * next; }; こんな構造体あって while(h){ pthread_mutex_lock(h->m); h->var++; pthread_mutex_unlock(h->m); h = h->next; } こんな風にリンクリストを舐める前後を排他して 舐めていくという処理は正しいでしょうか?
加算をアトミックにしたいなら正しいんじゃない。
>>388 では、これもレースコンディション無く
検索可能ですかね?
struct hoge{
int var;
int id;
pthread_mutex_t m;
struct hoge * next;
};
void search(id)
{
while(h){
pthread_mutex_lock(h->m);
if( h->id == id){
h->var++;
pthread_mutex_unlock(h->m);
return;
}
pthread_mutex_unlock(h->m);
h = h->next;
}
}
390 :
デフォルトの名無しさん :2009/02/09(月) 14:04:10
shared_ptrで管理するオブジェクトAをスレッドXに渡し、スレッドXからdllを呼んで、dll内でオブジェクトAのメモリを確保する、 ということをしたいのですが、以下のコードでjoin終了時、shared_ptr<A>の解放処理のところで例外が発生します。 どういった理由が考えられるでしょうか? マルチスレッドでもdllを使わなければ問題なし、dllを使ってもマルチスレッドにしなければ問題なしでした。 struct A {}; // スレッドXにshared_ptrで渡されるデータ typedef void (__cdecl* DllFunc)(std::tr1::shared_ptr<A>& a); // スレッドから呼ばれるDLL struct X { // boost::threadに渡すスレッドオブジェクト std::tr1::shared_ptr<A> a_; X(std::tr1::shared_ptr<A> a) : a_(a) {} // DLLに渡すデータ void operator()(void) { // スレッド実行時に呼ばれる関数 HMODULE handle = LoadLibrary(L"dll_func.dll"); DllFunc dll_func = (DllFunc)GetProcAddress(handle, "dll_func"); dll_func(a_); FreeLibrary(handle); c.notify_one(); } }; int main(int argc, char** argv) { std::tr1::shared_ptr<A> a(new A); std::tr1::shared_ptr<X> x(new X(a)); boost::thread th(*x); th.join(); // ここで例外発生 } <dll_func.cpp> BOOL WINAPI DllMain (HINSTANCE hinstDll, DWORD fdwReason, LPVOID lpvReserved) { return TRUE; } extern "C" __declspec(dllexport) void __cdecl dll_func(shared_ptr<A>& a) { a.reset(new A); // これがなければ大丈夫 }
よりによってここに書くか。すれ違いだWin32スレ行け。 DLLの勉強一からやりなおせ。 最初から全コードのせときゃもっと早く回答ついたんだろうが、ウザイからオシエネ。
DLL内でnewしたのをEXE内で解放したらエラー出るんじゃない? そもそもshared_ptrだって内部で参照カウント用にnewしてるからDLLじゃ使えない気がするなー。
393 :
392 :2009/02/09(月) 17:02:58
スレッドは全然関係ないね。うん。
>>390 たぶんこれだけで死ねる。
std::tr1::shared_ptr<A> a(new A);
X(a)();
DLLか・・・COMについて調べたほうがいいんじゃないですかね いろいろヒントあるよ
shared_ptr使ってるくせにdeleter知らないとか
>>288 Windows Xp home SP3 で自作のTCPサーバ運用してるけど、インバウンド接続の
同時接続数の制限が10ってことはないよ。
今モニタ見ても20人くらい繋がってる。
p2pがすごい数でつながってるだろうし
この件についてはいろいろなひとがよく確かめずにいろいろ書いてる。
自分でちょっとやってみればすぐわかる。
>>397 実装はともかくライセンスで制限されてるはず
そうなんだよね。 使わないでくれという約束で みんな破って使ってるわけだ。
SQLだったかで試してたときにイベントログに制限されたメッセージが 出たことある。あとShare動かしてる時とか頻繁に出る気がする。 単純にセッションの制限では無かった筈。
MS製のサーバは独自に制限した実装 IISじゃなくてPWSだっけ WMEとかはレジストリいじって50人くらいつないだりしてたな。
それとは別に、セキュリティ的な話で、 SYN_SENTなソケットをシステム全体で 10くらいしか持てないって制限もあったはず。
初心者な質問ですが、 Thread A Thread B for(;;) for(;;) printf("AAA\n"); printf("BBB\n"); という処理を行うと、AAA行とBBB行が入り乱れて表示されるんですが、 AABABB\n\n などと表示されることはありえないんでしょうか。 環境はWindows XPで、VC++2008EEでプログラムを書いてます。
406 :
デフォルトの名無しさん :2009/02/23(月) 21:19:24
スレッドに別のスレッドから信号を送って途中で処理をキャンセルしたいのですが、 現状、以下のようにしています。 void run() { // スレッド実行部 for () { // 長いループ ...処理... if (check()) return; // 処理をキャンセル } } check()でキャンセルのフラグをチェックし、このフラグを別のスレッドから書き換えるという方法です。 でもこの方法だとループ内の処理が重くなったときにキャンセル操作に対する反応も遅くなってしまうため どうしたものかと悩んでます。 スレッド内でタイマーのようなものを発行して、定期的にcancel()のチェックをするといった方法はできないでしょうか? 環境はVC9です。
>>406 別スレッドから強制停止するとリソースリークの元だよ。
if (check()) return; // 処理をキャンセル
を重い処理の途中に幾つか入れる方がまし。
408 :
406 :2009/02/23(月) 23:51:22
>>407 > を重い処理の途中に幾つか入れる方がまし。
どうも。やっぱりこういう単純な方法しかないですか。
重い処理を別スレッドで行わせながら
キャンセル操作の反応がよい安全な方法ってのはないんでしょうか。
cancel()を挿入しまくるというのもなんだかスマートじゃないなぁ・・・。
非同期に飛ばされるぐらいならコードが汚くなる方が良い と思うのは俺だけじゃないよな?
その重い処理ってのがなんなのか スマートとか言うならその重い処理をスマートに分割すりゃいいじゃない どうしてもチェックしまくりたくないっていうなら処理を持ってるクラスのインスタンスを急にnullにしてやって 例外捕らえて終了してしまえ、最悪だけど
別プロセスにして殺すってのは? 結局そういうのって要求されるキャンセル応答時間次第。 人間相手ならmsecオーダでおkでしょ。 きっとループ1回につき1msecもかからないのでは?
ワーカースレッド2つ以上用意にして 対処すればよくね? 複数個のスレッドでビジー状態になるなら その処理内容そのものを分割しタスク化した方がいい
違う質問スレで質問した後でこちらを見つけたので一応こちらでも・・・ CreateThread関数で第三引数をクラスのメンバ関数にしたい場合は どういう記述をすればいいのか教えてください よろしくお願いします
414 :
468 :2009/02/24(火) 02:56:15
>>410 >その重い処理ってのがなんなのか
例えば大きなサイズの行列計算や、待ち行列を使った探索問題なんかを想定しています。
問題を分割することはある程度はできるんですが、それはそれで頑張るとして、
それ以外のアプローチははないかなと。
>>411 > 別プロセスにして殺すってのは?
すみません。よくわかりません。
別プロセスならば殺しても元のプロセスに影響がでないという意味でしょうか。
>>410 の後半で言ってることに近い
>>412 > ワーカースレッド2つ以上用意にして 対処すればよくね?
同じスレッドオブジェクトをAとBの2つ用意して、
Aが動いてるときにキャンセルしたときはキャンセルしたふりをして
(Aの計算は次のcancel()チェックまで続いてる)、
新規の呼び出しがあったときはBを動かすというイメージですか?これはいけるかも…。
415 :
468 :2009/02/24(火) 02:58:01
>>413 コールバック関数にはstaticなメンバ関数(クラスメソッド)しか使えない。
コールバック関数を使うAPIは大抵ポインタ型の引数を渡せるから、
クラスを使いたいときはそこにthisポインタを渡して使う。
>>413 できない
普通の関数作ってその中で呼び出す
>>414 別プロセスにすると、ターミネートしたときのリソースの開放をOSがやってくれる
ってことではあるまいか。
それはともかく、その長い処理がうまく分割できず、どうしても時間がかかる場合は
汎的には、キャンセルボタンの入力を取得する側(フラグを立てる側ね)で、キャンセルが
押されたからしばらく待てっていうサインをユーザーに与える方が重要な希ガス。
別プロセスのほうがクリーンアップの点では簡単&安心だなあ ただ、多くの情報を受け渡したり、途中で通信が必要だったりすると しんどいけどな
しんどいと言うか、性能の問題がでるかも
422 :
406 :2009/02/25(水) 00:45:53
>>419 -
なるほど。別プロセスにすることも検討できそうです。
なんとなく雰囲気は分かりました。どうもありがとう。
処理毎に別プロセスって、昔の業務アプリみたいだな。っていうか、 今でもVBあたりでそんな開発やってそう。 1画面=1exeファイルで、画面間はsystem()でプロセス呼び出し。 画面フォーム上で入力したデータ等は、ファイルに書き出して渡す。 大抵、exeファイルの名前は全部数字と意味不明なアルファベットで、 メモリ食いまくりで、やたらに遅い。(w
大規模なアプリはマルチプロセスの方が開発しやすいね Windowsの場合は性能的にマルチタスクに向かないけど
>>423 unixだとマルチプロセスは多いけどな。
VB6のアプリだとそういう作りになるのは仕方ない。
モジュール分割の手段がCOMしかない。
20画面もあるとロードモジュールが10M超える。
IDEに読み込んだりコンパイルするのにも一苦労。
プロセス間でDBのセッションを引き継げたらマルチプロセスでも軽くなるはずなのだけど、
それも出来ないからDBの接続でどうしても画面遷移が重くなってしまう。
426 :
425 :2009/02/26(木) 01:19:09
>>424 マルチスレッドは、スレッド間のメモリ保護機構がないので、他スレッド
による破壊のリスクと引き換えに、高速なデータ共有が可能と思うが?
Windowsがマルチタスクに向かないとか、何を根拠に?
>>425 昔はメインメモリが少なく高価だったという事情もあるし、「unixだと」
という括りはどうかな?
20画面なんて、そんなに大きな規模なプログラムじゃないよね?その程度
の規模で単純にVBのソースだけなら、10MBを超えるようなことはないの
では?
確かにVB6当時のハード環境(Pentium 300MHz〜1GHz, メモリ64MB程度?)
でのビルドは遅かったかもしれないが、VBはVCよりは速かった様に記憶
しているけど?
それと、プロセス間でDBのセッションを引き継げないのは、VBや、Windows
に限定された話ではないのでは?
極端に処理が遅い業務アプリは、データベースの設計自体に問題があり、
無駄にDB間でレコードをコピーしたり、テーブルのリンクが必要だったり
ということが多い気がする。
プロセス間のデータ共有なら共有メモリがあるよ 特に親子関係があれば、mmap ANON とかでお手軽極楽 スレッドのメリットは(スレッド間なら)高速にディスパッチ出来る点だね heap だろうとなんだろうとメモリは全部共有されるというのは メリットでもあるけど、デメリットでもあるかな。 バグの原因になりがちだよね
構造化されたデータを別プロセスと共有メモリ経由でやりとりするとして c構造体ならまあなんとかなるんだが(いやそれでも大変だが) c++クラスだとすんごいやりにくい 何かウマい方法あります? 受け渡し用にクラス作るのもアホらしいし・・・ 変態的テンプレートでなんとかなるもんだろうか それとも単なる通信バッファとしてしか使わない?
C++ならCの構造体も使えるんじゃ…。
そういうのはソケット使って単純化してる。
プロセス間共有メモリは後で環境や仕様が変わったときに
変更が大変だし流用も難しい。バグも入りやすい。
パフォーマンスを上げたいとか、よっぽどの理由でも
ない限り使われないんじゃないかな。
スレッドと違って
>>428 の言うデメリットもあるし。
ウマい方法はありません。
>>426 酷いミスリードだな。>424はマルチプロセスによるマルチタスクという技法がWindows向けでないと言っているように見えるが。
IE8はマルチプロセスですぜ
unixといえば今でもパイプをfork/execで分け合ってというイメージが強いな。 DBのコネクションは知らないがファイルハンドルならプロセス間で受け渡せる。 Windowsにもハンドルを複製して子プロセスに渡すオプションはあるのだが、 OS/2やNTは最初からスレッドをサポートしてたのであまり使われない。
435 :
426 :2009/02/26(木) 17:42:01
>>425 ハンドルの複製に失敗しますた。orz 426=423です。
>>431 未だにWindowsがunixに劣っていると思っている原理主義者か、TRON房かも。
何を以ってunixを定義しているのか聞いてみたい。
>>434 ハンドルをコピーしたりは、MS-DOSにもあったかな。INT 28Hだか忘れたけど、
プリンタスプーラ用の割込使えば、一応擬似マルチタスクで一部のシステム
コールを呼べた。
デュアルコアやクァッドコアのCPUだと、マルチスレッド化すると理論上
2倍や4倍で動くと勘違いしているヤツもたまにいるよね。おまえのOSは
いったいいくつプロセスが動いていると思っているんだと、小一時間。(略
WindowsがUNIXより優れてると思い込んでるなら まずはその幻想をぶち壊す!
>>436 上条さん乙。
つか、んな事誰も言ってないから。
マルチスレッドスレでマルチプロセス云々言ってる時に何の前提もなく 「マルチタスク」なんて言う奴は普通にスルーでいいと思うんだけど...
よ〜し、おじさんもマルチプログラミングとかタイムシェアリングとかの古語を持ち出しちゃうぞ。
>>435 実質、4coreXeonのシステムだとOpenMPで4スレッドにして3.9倍速くなるけどね。
逆に、>435のCPUはOSをアイドル状態で動かすだけでどんだけ負荷喰ってるんだって話だな。
441 :
426 :2009/02/27(金) 10:22:04
>>440 スレッドでどんなコードを走らせているか知らないけど、スレッド内で
アクセスするデータもコードも、CPU内のキャッシュに収まるくらい
小さなプログラムでもない限り、そういう結果はまずありえないと思うな。
それとも脳内キャッシュ?
442 :
426 :2009/02/27(金) 10:43:15
非同期I/Oを使わずスレッド内でファイルI/O待ちしているとか、ネット ワーク物理層の帯域幅に比べて通信速度が遅く、スレッド化でマルチ セッション化できるといった、ある意味冗長な造りのプログラムなら ありえるね。 OSのアイドル状態を持ち出すあたり、他に何個のプロセスがいつ走って いるか考えていないのかな?(w
>>441 OpenMP知らないなら黙っていた方がいいと思うよ。
>>443 3.9倍早くなるって
作ったプログラム全体?それとも特定の処理に
限定された内容?どっちなの?
445 :
443 :2009/02/27(金) 11:04:31
>>444 私に聞くなw
恐らく演算に集中している部分じゃないの?
MKLなんかは大き目のデータのFFTでそれくらいのリニアリティを叩き出すから。
embarrassingly parallel なワークロードならそれくらい行ってもおかしくない でも大抵の処理は並列化不可能な部分が無視できない量存在してて、 アムダールの法則でもって高速化の限界が簡単に見えてしまうと思うよ
>>436 コンシューマー相手のソフトウェアのパッケージ販売の観点からは
明らかに優れている。全然スレ違いだが。
>>443 OpenMP に期待しすぎ。
何でもかんでも 3.9倍になる魔法なら俺も欲しいが。(w
>デュアルコアやクァッドコアのCPUだと、マルチスレッド化すると理論上 >2倍や4倍で動くと勘違いしているヤツもたまにいるよね。おまえのOSは >いったいいくつプロセスが動いていると思っているんだと、小一時間。(略 略とか言われても。誰か解読してあげてよ。 少なくとも実測で3.9倍でてるわけだから、理論上は4倍出ると言っても問題ないよな。 たくさんのプロセスが動いてるとき、マルチコアだとちゃんと速くなるよな。 意味不明。
どういう問題を解いて3.9倍なのか書かないと意味がないかと。 知人の計算屋さんがAMDの8CPU機にメモリしこたま積んで 巨大グラフを相手にした問題を解いていたことがありましたが、 問題の構造上メモリアクセスに局所性が全くないのでCPUの 速度や数以前にメモリ帯域が飽和して速度が頭打ちになると ぼやいていた事が。
>>450 まあその辺に桁違いのコストを掛けてクリアしてることが
スパコンの存在意義だしね
452 :
443 :2009/02/28(土) 16:53:30
>>448 期待するも何も、実験した結果だし。
>>450 >445に書いた通り、只管FFTを計算するようなプログラムと言うくらい。
その結果では、4core2cpuのシステムで、4並列まではびっくりするほどリニアリティがあるけど、
その先は一つ増やしても0.7個分くらいしかパフォーマンスが上がらなかった記憶が。
# 8並列で7倍くらいかな? 必要なら記録を探してくるけど。
尤も、自作のプログラムだと4並列でも8並列でも殆ど変わらなくて泣けた罠。
インテル某氏の話だと、MKLはOpenMPで並列化してもリニアリティを確保できるように
作られているそうで、折角FFTを使わない版を作ったのにお蔵入りになりそうだったり。
スパコンと言えばTOP500で10位にWin鯖クラスタが付けてたけど (CPUとメモリだけ)似たような構成の他のと比べて特に劣ってるようでも秀でてるようでもなかった
>>452 OpenMP に頼って満足してる人はこのスレに用はないでしょ。
どうぞお引取りください。
>>454 >452じゃないけどここはマルチスレッド全般でしょ?
>1にも「OS・言語・環境は問わない」って書いてるんだからいいと思うけど
ただし>452=443=440はおバカさんだと思うけどねw
OpenMP の話題がまずいと言ってるわけじゃなくて、「OpenMP に頼って満足してる人」って書いてあるんだが...。 スレタイに「相談室」って書いてあるのが見えませんか?
>>456 相談した人にOpenMPに頼って満足してるってレスするのは問題ないだろ
で、どこに相談した人がいるんだ? (w
俺は>452個人の話はしてないんだが。お前誰と闘ってるんだ?
460 :
452 :2009/02/28(土) 22:13:07
まぁ、私は「OpenMPに頼って満足してる」のではなく、「OpenMPを巧く使うMKLに勝てなくて泣いてる」のだけれどねw
よくわからないけど、置いときますね。 #light open System.Threading let tid = fun () -> Thread.CurrentThread.ManagedThreadId let sleep = fun (t:int) -> System.Threading.Thread.Sleep t let x1() = [|1..100|] |> Array.map(fun x -> sleep(100); [|x ; tid()|]) let x2 = [|1..100|] |> Array.map(fun x -> async { sleep(100); return [|x ; tid()|] } ) |> Async.Parallel let _ = printfn "%A" (x1()); printfn "%A" (Async.Run x2)
>>450 おれは、
>>452 個人の話をしてるんですけど。
まさか、
>>454 に書いてあるアンカーすら見えなくなるほど
頭に血が上ってるとか? (w
>>462 俺は「OpenMPに頼って満足してる」のを理由に追い出そうとしたことに
ついて話をしている。
>>452 個人のことはどうでもいい。
どうやらただの煽りあいになりそうだからこの話題は終了する。
>>460 何故勝てなくて泣く必要があるのか少し気になる。
>>463 「相談した人もいないのに勝手に OpenMP に頼って満足してる人」は
このスレに用はないでしょ。
これでいいか?
>
>>452 個人のことはどうでもいい。
#
>>452 にレスしてるのに、勝手に割り込んできて逆切れかよ...
OpenMPってどんなの?たとえば、Videoのエンコード・デコード 処理が書いてある逐次処理のCなりC++のソースコードが あったら、ほとんど変更なしに並列化できるん? それとも、既存のソースは一から書き直しくらいしないと パフォーマンスは出ない?
それ以前に446にふさわしい言葉は「ググれカス」だろう。
>>466 OpenMPスレという物もあってだな(ry
OpenMP詳細しらんが、既存のソースは1から書き直しまで いかなくても、大幅に書き直さないとパフォーマンスは でないのだろうな。常識的に考えて。 コア数に応じてリニアにパフォーマンスがあがって、既存 のソースから簡単に移行できますよ、っつーなら神なのだが。
それを可能にするには関数型など副作用のない言語が有利 今更言うことでもないが
>>471 んなこたーわかってんだよ。新規にはじめる分野はそれでもえーよ。
資産の移行も重要なんだよ。
おまえの書いたコードなんぞ資産と呼ぶ価値も移行する価値も無いから気にすんな
>>473 俺の書いたコードが資産だなんて、いついったんだよ?
煽るにしろ、頭の悪さが透けてるんだよ。
>>472 の「おまえ」が
>>474 だなんて、いついったんだよ?
煽るにしろ、頭の悪さが透けてるんだよ。
これは惨めなミス。
>デュアルコアやクァッドコアのCPUだと、マルチスレッド化すると理論上 >2倍や4倍で動くと勘違いしているヤツもたまにいるよね。おまえのOSは >いったいいくつプロセスが動いていると思っているんだと、小一時間。(略
>>477 こいつの言ってることまじでわからんのだが・・・。
こいつがアフォなのか、俺がアフォなのか誰か解説よろしく!
コア1 ●◎◎◎◎◎◎◎◎◎ コア2 ●○○○○○○○○○ コア3 ●○○○○○○○○○ コア4 ●○○○○○○○○○ ↓ コア1 ●◎◎◎◎◎◎◎◎◎ コア2 ●◎◎◎◎◎◎◎◎◎ コア3 ●◎◎◎◎◎◎◎◎◎ コア4 ●◎◎◎◎◎◎◎◎◎ ○ 空き ● 別プロセス ◎ 自プロセス 4倍になる
>>477 基本的には
>>477 がちょっとずれていると思う。
コア数に比例してリニアに2倍4倍にならないのは事実。
でもハウスキーピングなプロセスの数云々は性能を押し下げる
理由としてはどちらかというとマイナーな部類だと思う。
ちょっとゲロでちゃった
並列化効率の話がまず最初だよね。 アムダールの法則。
>>480 いや、こうまで単純化していいかどうかわからんが、
ハウスキーピングのプロセスがほぼsleep状態と
仮定したら無視できるわけで。
というより、4コア100%使用する処理走らせるんだったら、
無視できるほどなわけで(スワップデーモンとか
ハードアクセスの重いスレッドが走らない前提なら)。
バスネックでリニアに伸びないとか、キャッシュの競合
だとかいうならまだしも。やっぱり俺には
>>477 はさっぱ
りわからん。
アイドル状態のプロセスでもビジーループでCPU消費してる とか思ってんじゃないの
>>484 単に1つのプロセスが1コアを占有し続けると考えているのではあるまいか。
486 :
デフォルトの名無しさん :2009/03/14(土) 05:22:42
マルチスレッドについて質問です。
環境は VC++2005 SDK です。
子ウィンドウの WM_CREATE にて無限ループをさせても
親ウィンドウが操作できる
事を実現したいです。
他スレにて、
>Windowsのウィンドウはスレッドに属する。
>ウィンドウプロシージャはウィンドウの属するスレッドで実行される。
>さて、どのスレッドに属するかというと、CreateWindow(Ex)を呼んだスレッド。
というレスをいただき、新しいスレッドにてCreateWindow する手段を取りました。
子ウィンドウの WM_CREATE までは処理が進むのですが、
無限ループどころか for (i=0; i<100; i++) { i = i; } を WM_CREATE 内に
記述した途端にフリーズする様になってしまいました。
コメントアウトすれば、問題なく動作します。
ファイルをアップロードしたので、見ていただけないでしょうか?
ttp://www3.uploda.org/uporg0077.cpp.html 受信パスは test です。
どのように修正すれば良いか、ご教授願います。
よろしくお願いします。
>>486 windowsのウィンドは、プライマリスレッドで生成しないと
いろいろいろいろいろいろいろいろトラブルが起こるので、そういう設計は見直した方がいい。
そもそも子ウィンドウは親ウィンドウと同じスレッドで生成しないとトラブルになる。
例えば親をAスレッドが、子をBスレッドが作ったりすると、
親のプロシージャはAスレッドが実行し、子のプロシージャはBスレッドが実行することになる。
子から親への通知や親から子への通知がメッセージで発生したら発生したら、
デッドロックの宝庫になることは想像に難くない。
それ以前にメッセージループって親子で共通のような気が・・・
>>486 アップロードしたプログラムだとそもそも子ウインドウは表示されないだろ。
動くようにするには子ウインドウと呼んでいるものを、新しいスレッドのウインドウにすること。
つまりメッセージループをそこでまわす。
MSG msg;
ShowWindow(hChild, SW_SHOWDEFAULT);
UpdateWindow(hChild);
while(GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
//static int k = 0;
//k = 1;
//while (1)
// k++;
WM_CREATEで無限ループしたらCreateWindowから制御が戻らないわけだが
490 :
486 :2009/03/14(土) 15:00:34
>>487 色々と問題があるという事ですか...
そこまでは考えておりませんでした。
ですが、今はこの枠組みで作ろうと思います。
アドバイスありがとうございます。
>>488 メッセージのループを回すのを忘れておりました。
ありがとうございます。
ただ、今回はメッセージのループのみが欲しいので
ウィンドウは非常時で構いません。
>>489 確かにそうでした。
あるメッセージを受けた時に
その中で Sleep(1000); を実行する事にしました。
・・・が、それでも親ウィンドウが 1000 ミリ秒 固まってしまいました。
以下の様にしておりますが、
これでは各ウィンドウは別スレッドで動かないのでしょうか?
ttp://www2.uploda.org/uporg2088151.cpp.html 受信パスは test です。
よろしくお願いします。
作ろうと思います、じゃねー 動作が未定義なんだからそんなプログラミングすんな
>>491 互いのウィンドウでメッセージのやり取りを頻繁にするような事は致しません。
親スレッドとは独立したウィンドウプロシージャのメッセージループ
(表現が合っているかは自信がありませんが)が欲しいのです。
以下、長文失礼します。
5 [msec] の情報が入るサイズのバッファを複数用意し
信号をバッファに入力し、あるバッファが満タンになったら
windows からメッセージが投げられ、
受け取ったメッセージ内で信号処理をする、
というものを作っています。
この時、信号処理に時間がかかるため
常にメッセージを受け取った時の処理を行ってしまい
メニュー操作が出来なくなる状態です。
アプリケーションを強制終了すると、信号処理した数値列が
ちゃんとファイル出力されているので
信号の入力及び信号処理は問題なく進んでいます。
これを解決するにはメニューを持つウィンドウと
メッセージループのあるウィンドウを別スレッドで走らせれば良い
と考えました。
493 :
492 :2009/03/14(土) 15:53:32
連稿失礼します。 Sleep(1000); を int i, j; for (i=0, j=0; i<1000000000; i++) j++; としてみましたが、結果は同じでした。 親ウィンドウのスレッドにフォーカスが戻っていないのでしょうか?
子ウィンドウ作る必要なんて無いところを、 わざわざ回りくどいやり方しているようにしか思えないんだけど。 ワーカースレッドにデータ送りたいだけじゃないの?
>>494 ワーカースレッドについて知識が無かったのでググってみました。
MFCでのみ使用可能な関数でしか作れない事が判りました。
今はSDKで組んでおり、MFCは使った事が無いので今の私には使えそうにありません。
情報ありがとうございました。
>>495 ワーカースレッドは概念であって、SDKのみだから作れないということは無いよ
そもそも、貴方のやろうとしていること自体がワーカースレッドの利用だ
>>496 ワーカースレッドについて調べ方が間違っていたようです。
もっと調べを進めます。ありがとうございます。
>>492 ワーカースレッドというのは、作業を行うスレッドという程度の意味です。
信号処理中はGUIが不要のようですので、GUIは1個のスレッドにまとめて下さい。
以下、基本は次のような処理になります。Q0とQ1のアクセスを排他制御して下さい。
プライマリスレッド
メインウィンドウの作成。
バッファ群を作成する。例えば5ms用のバッファをN個作成して、
2個のキューQ0(未使用バッファ用)とQ1(充填済みバッファ用)を作成する
バッファを全てQ0に格納し、スレッドA・Bを作成・実行する。
以降はGUIによるスレッドA・Bのコントロールを行う
スレッドA(バッファ充填処理)
1.信号受信処理の初期化
2.Q0からバッファを取り出す。無ければ待つ。
3.バッファを充填する処理(この辺で外部からのスレッド終了通知チェック)
4.バッファが一杯になったらQ1へ入れ、2へ戻る
スレッドB(信号処理スレッド)
#スレッドAで、Q1の格納数が0->1になったとき起こされる。
1.Q1からバッファを取り出す(なければ待つ)
2.信号処理(この辺で外部からのスレッド終了通知チェック)
3.結果の出力
4.バッファをQ0へ入れ、1へ戻る
501 :
492 :2009/03/15(日) 20:45:19
>>498 詳しい構成、本当にありがとうございます。
頑張って理解してみます。
void A::sync_fun() { boost::mutex::scoped_lock lock(m_); // 何かの処理 } 上のlockで待機しているスレッドがあるときにAのオブジェクトをdeleteするとスレッドは待機したままですね。 下のようにするかtimed_waitにする必要があるのか、そこまで気にすることもないのか。 みなさんはどうされますか? void A::sync_fun() { boost::mutex::scoped_lock lock(m_); cond_.wait(lock, bind(&A::pred, this)); if (invalid_) return; // 何かの処理 } bool A::pred() const { return stat_ || invalid_; } A::~A() throw() { { boost::mutex::scoped_lock lock(m_); invalid_ = true; } cond_.notify_all(); }
>>502 どうするかは、何のクラスかによるだろう。
一般論でAが、sync_fun()実行中に破棄される可能性があって、
どうしても回避できないならAのデストラクタでunlockする。
ダウンローダをマルチスレッドで作成しようと思っているのですが スレッドを10個作り それぞれにURLを追加して、次々にダウンロードさせる仕様にしようかと思っていますが このスレッドの終了タイミングはどういった条件で終了すればいいでしょうか? メインスレッドが終了するとこの10個のスレッドも終了するので どうしたものかと考えています
あげます すいません
506 :
デフォルトの名無しさん :2009/04/04(土) 16:20:37
.
>>504 何を聞きたいのかよく分からんけど、
メインスレッドで10個のスレッドの
終了待ちさせれば良いんでないの。
>>507 なるほど
そういう手がありましたか
ありがとうございました
何か一冊マルチスレッドの本読むのおすすめする
class Hoge{ public: void End(){ /*他のスレッド、シグナルハンドラとかから呼ばれる */ Lock_.GetLock(); // 実際はRAII使ってるよ continuable_ = false; //その他のリソース会報処理 } void Task(){ // thread poolから実行されるタスク。 Lock_.GetLock(); if( continuable_ == false ){ return; } // IO処理とか色々非同期でやる } }; なんか、フラグ使ってやるのが嫌なんだけど、 非同期で実行されるオペレーションをキャンセルさせる スマートな方法ってない他にない? この実装は間違ってる?
いいんじゃねえの。 スレッドを自発的に終了させるには スレッド自身が何かをチェックしなけりゃならんし。
間違ってないし、フラグを使う方法は普通によくある
別プロセスにしてkill -9、これが最強。
せめてSIGTERMでやんわり殺してやれよ。
そうそう、せめて覚悟する時間くらいは与えてあげないと。 尤も、そうすると逆切れして殺しに来るかも試練が。
516 :
デフォルトの名無しさん :2009/04/09(木) 00:33:31
変数か構造体かクラスのインスタンスa,b,c,dがあるとして、 まず、スレッド1がaとbを使用、スレッド2がc,dを使用する。 その後、スレッド間通信とかでスレッド1も2も上のa,b,c,dを使用した処理が完了したことをスレッド1,2に伝える。 そして、スレッド1がa,cを使用、スレッド2がb,dを使用する。 といったような処理をするときに、特別にロックとか必要ですか。
>その後、スレッド間通信とかでスレッド1も2も上のa,b,c,dを使用した処理が完了したことをスレッド1,2に伝える。 これで同期取ってるから、そこをちゃんとすればよい。
弱い順序付けの場合だめな場合がありえるかもね
ねーよw
グローバル変数keyに対して、他のスレッドで値を変更してループの続行、終了を決める場合に while ( key ){ count++; } というコード書くとコンパイラの最適化によって、無限ループになる可能性があるということですが、 while ( *pk ){ count++; } のようにアドレスから参照しようとしても同じことになるのでしょうか。
わかんない。 つーか key を volatile にすりゃいいんでない?
volatileで大丈夫そうですね。ありがとうございました。
マルチスレッドがどういうタイミングで割り込まれるのかわからないのですが たとえば、if(++i == n) のコードなら iをインクリメントしてからnを比較するまでの間で 割り込まれる可能性はあるんでしょうか?
あるよ そもそも正しくインクリメントされることも保証されない (CPUやコンパイル出力によるけど) なぜなら、 (1) メモリからiの値を読み出す (2) 値+1を計算する (3) iの領域に計算結果を書き込む という3ステップになる可能性があるから
>>526 そのステップ間で割り込まれるんですか、結構分割されるものなんですね
ありがとうございました
>>527 ただし、いつもそのように分割されるとは限らない。
529 :
デフォルトの名無しさん :2009/04/13(月) 22:54:34
volatile最強杉www
fread等でのデータ読み込みをシングルスレッドで実行する場合と マルチスレッドで実行し、メインスレッドでは出来るだけ何もしない場合の速度は同程度になるものでしょうか?
>>530 速度は実測が基本。
たぶんその比較内容だと、激しく環境(ハードウェア、OS、コンパイラ)に依存する。
532 :
530 :2009/04/14(火) 10:57:26
WindowsXP、vc2003、C2D E7200です。 timeGetTimeで測定した所、 マルチスレッド側の速度が安定しないのですが、 100kb程度のデータで2倍、1mb程度だと4割程度の速度差になりました メインスレッドは以下のようなループになっていています while(1){ if(PeekMessage(&msg,0,0,0,PM_NOREMOVE)){ TranslateMessage(&msg); DispatchMessage(&msg); } else { // メインスレッド } }
色々条件がよく判らんが、ここが一番判らん。 >100kb程度のデータで2倍、1mb程度だと4割程度の速度差になりました 2倍の速度差と4割の速度差ってどういう意味なんだか。 シングルスレッドに対してマルチスレッド版は2倍の速度差、つまり3倍所要時間が掛かったのか?
534 :
530 :2009/04/14(火) 11:11:23
すみません、 所要時間 シングル マルチ 100kb 0.013秒 0.025秒 1mb 0.100秒 0.140秒 です
>>530 マルチスレッドは、複数のことを同時にしたいときに使う技術なので、
そういう視点で選択した方がいいですよ。
ただ速度といっても、プライマリスレッドからストレージアクセスを
しているときキャンセルボタンを押したいんだけどその反応が鈍い、とか、
ストレージをアクセスしながらムービーを表示しているのだけれどコマ落ちする、とか、
単純コピーを速くしたい、では、とるべき手段に違いがありすぎます。
単にあるデータをストレージから読み込む処理だけに着目するなら、シンプルな
シングルスレッドの方が高速になることが多いと思います。
予め別のスレッドで利用するファイルを予測してアクセスし、キャッシュに入れておく
などというのはまた別の問題ですが。
536 :
530 :2009/04/14(火) 11:33:30
>>535 ありがとうございます
極力シングルで動作できるような方法考えることにします
>>435 Phenomの2コアで2スレッド動かしたら2.2倍以上のスコアを叩き出した。
確かに2倍になる訳じゃないね。但し、配列をL2とL3に合わせて巧く分割
できた場合に限るけど。あと、OSのや他プロセスのボトルネックがある分
やっぱりマルチコアの方が早いね。実質90%でしか動けないシングルは倍
にしても180%だけど、90%+100%で動けるマルチコアだと実質190%で10%
ぐらい早くなる。
>>521 別にvolatile使わなくても問題なくね?
static int key=1;
void Thread0()
{
key=0;//volatile指定が無い場合消失する可能性がある。
Sleep(100);
key=1;
}
void Thread1()
{
while ( key ){ count++; }
}
こんな事でもしない限り無限ループにならんべや。
こんなコード書くことまず無いだろ。
それと、そもそも、グローバル変数使うなよ。
>>538 まず、ネタなのかマジなのかを書いてくれ。
volatileを使うと排他制御しなくて よくなるから必要
それは誤り
keyをテストする所にメモリバリア入れないと駄目じゃないかね
例えばJavaやC#などだと参照してる変数がvolatileだと期待通りに動くが、 そうじゃないとどうなるか分からんのじゃない?
>>543 volatileと排他制御はなんの関係もないぞ。
volatileは最適化の抑止で、せいぜい
>>538 の様な事や
レジスタだけでなくメモリ側にも変数を割り当てるぐらいだ。
そもそも、CやC++に排他制御なんて概念は無いから
クリティカルセクションなんかを使う他無い。
ちなみに、Javaは排他制御がかかるが、グローバル変数
と言っているからCかC++だ。もしかして、間違えてないか?
で、
>>539-541 は、人をバカ呼ばわりしただけの
まっとうな理由あるんでしょうねぇ。まさか、Javaや
C#のvolatileしか知らない癖にバカにしてたなんて
恥ずかしい理由じゃありませんよねぇ当然。
| J
【OS】WindowsXP SP3
【言語】C
ソース
ttp://f50.aaa.livedoor.jp/~iwazaki/uploader/src/up2117.txt ↑をcygwinでコンパイルすると
In function `thread_func':
14: warning: assignment makes integer from pointer without a cast
In function `main':
54: warning: passing arg 3 of `pthread_create' from incompatible pointer type
というエラーが出ます。
14行目と54行目が悪いことはわかりますが具体的な原因がわかりません。
ちなみにexeファイルは生成されます。
よろしくお願いします。
>>550 4: warning: assignment makes integer from pointer without a cast
In function `main':
キャスト無しじゃ整数をポインタにできないっていうような事書いてあるね。
pthreadのプロトタイプはこんな感じで第3引数には関数ポインタを、第4引数にはvoidポインタを取るように
なってる?
int pthread_create(pthread_t * thread, pthread_attr_t * attr, void * (*start_routine)(void *), void * arg);
君のコードだといずれもdoubleにキャストしているけど何故だい?
pthread_create(&a[i], NULL, (double *)thread_func, (double *)array);
※スレッドなんて飛躍したものに手を出す前にこの手のエラーを自己解決できる
程度には言語機能を勉強し直した方がいい。
>>550 んだんだ、
それに、Cなんだから、void * が絡むときはキャストしない方が
素直で、読みやすいコードになる。
たとえば、
double *data = (double *) arg;
は、
double *data = arg;
としろ、ってことね。C++から来た人はこれをやりたがるのね。
C++だとこの場合にもキャストが必要だから。
乱文澄まそ
>>551 pthread_create(&a[i], NULL, (double *)thread_func, (double *)array);
は単に見落としていたようです。
お手数掛けて申し訳ないです。
直したらこの行のエラーは出なくなりました。
>>552 C++をやっていたわけではないのですが、配布されたソースコードの例にはこの形で書かれていたのでそれに準じて書きました。
そしてまだ14行目でエラーが出ますがpthread_selfの扱い方はそもそもこれでよいのでしょうか?
ちょろっと調べて出てきたものを使っただけなのでよく理解していません。
554 :
553 :2009/04/21(火) 02:06:23
すみません、調べたらわかりました。 ただし他の問題が浮上しました。 pthread_t型をint型か何かに変換できないんですかね・・・。
>>554 pthread_tはポインタか構造体かなんかでしょ。
そもそも、別の型に代入しちゃいけない。
語のライブラリだと結構やろうと思えば別の型
に無理やり代入する事も出きるけどしちゃいけない、
内部に干渉しちゃいけないものがある。
大体識別値(discriptor)と呼ばれるものなんかがそう。
あと、初心者の内はメモリ操作が簡単にできる事が解って乱用する
人がいるがポインタのキャストはやたらめったらつかうもんじゃない。
てか、君の悩みはスレッド以前の問題だから、Cの初心者スレなんか
で質問しなさい。
言い方は気にくわないなw
小さい芽潰して楽しんでるふうにしかみえねーよ老害
>>554 pthread_tはunsinged longのtypedefだよ
>>556 何を言ってるんだおまえは?
>>550 のwarningを100回読み直してから出直してこい
>小さい芽潰して楽しんでるふうにしかみえねーよ老害 ふーん 芽をつぶして楽しんでて害なんだ ふーん
そうなんじゃね、多分。
大人なんだからもっと仲良くしろよ
歯痛制御で俺の虫歯を何とかしてくれ
チュイーン ギキィィーー
563 :
555 :2009/04/22(水) 22:56:29
>>556 俺、21歳なんだが。3D関連でC++始めて5年以上にはなるが、
そうか俺も、もう老害か・・・。
>>564 医者の趣味グラマっておおいな。
LHAも医者だし猫プロの筆者も医者。
しかも、本業より優秀そうなんだよな・・・。
本当は工学系にいきたかったのに、 なまじっか頭いいと医療系への進学を勧められちゃう奴って多いからな
いつも思うんだけど、歯科治療技術も日々発展してるだろうから 古い医者より新しいところの方がいいのかねえ
ジャストシステムのスタートアップにも医学生がいたな。 人間って本当に不公平にできてるよ。
>>564 予約時間の十分前には歯科に着いているのに
待合室で一時間待たされ、診察室に通されたと思ったら
また三十分以上待たされるのを何とかしてくれ
どう見ても歯科医と歯科助手がデッドロックを起こしているようでなかなか回ってこない
570 :
デフォルトの名無しさん :2009/04/23(木) 19:35:34
>>569 誰がうまいこと言えとw
デッドロックは言いえて妙だったわ。
>>567 少なくとも、レントゲン撮影したら「現像するから日を改めて」なんてところは止めた方がいい。
今時、治療椅子ごとに端末があってそこで見られるのが当たり前。
>>571 端末は無いけど、数分で現像したフィルムができるのが普通じゃない?
2,30年前からそうだったと思うんだけど
いい加減にしとけよ
574 :
デフォルトの名無しさん :2009/04/24(金) 11:57:45
マルチスレッドと減増 関係あっても、遠い存在のような
俺の日記帳 今日は5月2日です。 何してるの?
577 :
デフォルトの名無しさん :2009/05/04(月) 23:25:22
C++0xではマルチスレッドプログラムを組むのは 容易になるのであろうか
C++でマルチスレッドは危険ですよ
>>578 Win32本では平気でマルチスレッド走らせる例が書いてあるけど
デッドロックについても詳しく説明してある
CやC++の言語レベルではマルチスレッドについての取り決めはない。 ライブラリ(pthreadなど)やプラットフォーム(osやハードウェア)や実装(コンパイラ)レベルで、 扱いが決められているので、そういったものの前提抜きでマルチスレッドは語れない。
メモリモデルの仮定が入っちゃうからやりにくいだろうなあ
>577 concurrency 周りが大幅に強化されてるんで、恐らくは。
マルチスレッドにする利点は何? 複数の処理を同時に走らせることができるなんて妄想は無しで。
世界の全てが妄想なので、答えは消滅しました。
複数の処理を同時に走らせることができる、妄想で無しに。
個人的には
>>584 が何故「複数の処理を同時に走らせることができる」ことが妄想だなんて妄想を抱いたのか知りたい希ガス。
マルチスレッドの利点は全てそこから派生しているはずなのだが。
>>587 TSSは同時ではないとでも言いたいんじゃないか?
>複数の処理を同時に走らせることができる ってのはいわゆる手段なんで。 大元の目的は「暇をもてあましてるリソースを有効活用する」だな。 マルチスレッドはCPUがヒマしてる場合の、GPGPUはGPUがヒマしてる場合の手段だな。 >584がどんな妄想してるか迄はわからんが。
>>589 それ以外にもあるぞ。むしろプログラマ的にいちばんうれしいのは、コンテキストの異なる処理を明示的な切り替え無しに同居させられることじゃなかろうか。
重い処理を別スレッドでガリガリ処理しつつ、その進行状況をGUIで表示するとか。
ハァ? すべてをファイル・デバイスにしてそれをpollすればシングルスレッドで可能ですが何か?
スレタイ無視
昔のunixはスレッドなしでもfork/execだけでたいていの事はやれてたな。
>>591 ちょっと話違うが、Androidのセンサーまわりの設計もそんな感じ。
だが、そのファイルディスクリプタをもらう元が、1つしかなかったり
してセンサーごとにドライバが作れない。
1.0のころはモジュール化すらされてなかったり、1.5になっても
いまだダセー設計だし。設計したやつの顔が見たいな。
ドライバといった低レベルI/O処理の基本はスレッドより割り込み。 割り込みがないディバイスだとポーリングも使うけど。
何かの処理で待ちも含めてぐるぐる回りながら、他の処理も同時にやりたい、とかいう場合に いちいち処理を細切れにしてpollを含むメインループから呼び出す形に縛られるのは面倒だわな。 マジレスすると。
>>593 でも今はマルチスレッドがサポートされているということは、その煩雑な方式では力不足だったってことだよね。
今のところは、 やることを細切れにできるようにしておいて pollするスレッド(大半の時間は待機)が 少数のワーカーに仕事を振り分け ワーカーはひたすら仕事だけを待ちつづける、というやり方が I/O待ちやマルチCPU(コア)を有効に生かせ、 メモリやコンテキストスイッチのロスも少なく出来ると言われてるな。
開発効率という効率を無視すれば、それがベストだねw
OSのスケジューラをエミュレートしてるだけのような
コア数を大幅に越えるスレッドを生成すると、 コンテキストスイッチのせいでむしろ性能が低下する。ってのは本当なの? 実測して確かめたいんだけど、どういうコードを書けばいいのか解らん。 えろいひと教えて
スレッドプールにすりゃ解決よ
>>601 本当
スレッドに手を出した頃それに嵌ったことがある
各スレッドの同期にmutex/conditionを使う形で大量のスレッド作って試してみればわかるよ
むやみにスレッド数を多くするのはそもそも設計が良くないです
604 :
デフォルトの名無しさん :2009/05/10(日) 16:01:38
オーバーヘッドが増大する。 スレッドの多さは関係無し。 たとえば1ms以内で終了するスレッドを生成すれば効率悪い。
>>601 スレッドって、一般にはコンテキストスイッチが入らない
(だから軽い)というモノだろう?
原理的には性能低下は無い。
但し、実際のところコア間でキャッシュを共有してたり、
メモリバスを共有してるので、複数のコアを同時に使うことで
シングルコアよりも性能低下することはありうる。
マルチスレッドのプログラム組んでるんでて ある変数に複数のスレッドから同時にアクセスできるときは 排他的処理しないとだめ? というか たぶん今のエラーはそうだろうと思う
607 :
デフォルトの名無しさん :2009/05/10(日) 16:24:10
複数スレッドからアクセスしても、OSがエラーはいたことはないな。 値は、ぶっ壊れるけどね。
読むだけなら問題ない
609 :
デフォルトの名無しさん :2009/05/10(日) 16:29:54
読み書きしても、エラーでたことない。 たとえばグローバルsum=0に、複数スレッドから足し算してもエラーで停止しないが。
610 :
デフォルトの名無しさん :2009/05/10(日) 16:31:49
どういった場合に、メモリーエラーが起こるのかが知りたい。
>>605 > スレッドって、一般にはコンテキストスイッチが入らない
今コンキストスイッチしないのって絶滅危惧種だろ
なるほど 変数がスタックで削除したり追加したりだからダメなのか
>>605 マテ、スレッドでもコンテキストスイッチは発生するぞ。
スレッドが(プロセスに比べて)軽いのは、スタックとレジスタだけ
切り替えれば済む(これもコンテキストの切り替えだ)からであって、
コンテキストスイッチそのものが行われないからじゃない。
1CPUの場合はタイムスライスだけになるから減らないが、 CPUが複数ならスイッチ自体を減らせるという話じゃないかい。
>>613 ユーザランドでのスレッド実装だと
カーネルモードに入る回数が少なくて済むとかじゃね?
というかこの手のは、何が重いか時代により激しく違ってくるから
一般論といってもそれが何時のものかによるなあ
昔を語るのが一般とは思えない。
617 :
601 :2009/05/11(月) 22:46:47
時代によって変わるもんなのか。
レジスタ、スタックの退避とか、カーネルに入って出てくる処理とかが重いのかとかとか思ってたんだけど。
fiberは軽いよ。とか聞くけど、それはおいといて。
>>603 mutexとか排他は考えないで、純粋に「コンテキストスイッチ」処理がどれくらい重いもんなのか
図りたい。
linuxでpthread使ってやろうと思ってるんだけど、どんなコードを書けばいいんだろ
単純に0から0xffffffffまで足す処理をシングルスレッドでやるか、
0〜0xffを足す処理を0x1010101個のスレッド立てて計算させて、どっちが早いか。とか?<そりゃないだろって
618 :
デフォルトの名無しさん :2009/05/11(月) 22:57:13
例えば 20ms(OS次第)以上かかる計算処理を一つのJobとして Job計10000個をキューに入れる。 スレッドをプールしておいて、各スレッドはキューからJobを取り出してひたすら実行する。 この時、プールするスレッド数をプロセッサ数と同数の場合と2000個の場合とで実行時間を計る。 現実的には、スタック領域以外にも 各スレッドで多少の独立したメモリ領域は使うことが多いと思われるので ただの(レジスタやスタックで納まる)計算はではなく、 16Kなり64Kなりの領域をスレッド毎に確保しておいて その内部の値を使った計算とする。 等というのはどうだろうか。
別にキューに入れる必要無いな。 同じことを繰り返すだけなんだから、CASを使ったカウントアップだけして 一定の数字になったらスレッド終了で充分か。 これなら、共有メモリを使えば、プロセスとの比較も出来る。 ただ、スレッドは「スタートのシグナル」を全部同時に出すことが出来るけど プロセスだとどうなんだろ。全然知らない。
621 :
デフォルトの名無しさん :2009/05/21(木) 21:54:47
昔はPVM、今の時代はMPI そしてOpenMPとMPIのハイブリッド実行が主流なのだろうか
>同じことを繰り返すだけなんだから、CASを使ったカウントアップだけして >一定の数字になったらスレッド終了で充分か。 こんな非現実的な処理の時間を計測して何の意味があるわけ?
おそらくプロセッサ(コア)が増えれば増えるほど遅くなると思うけど。
ああ読み違えてたすまんのう 単に処理繰り返し数のカウントで使うだけってことね…
VC(VisualStudio2005)でコーディングしております。 「g_hThread = (HANDLE)_beginthreadex(NULL,0,MainLoop,0,0,&g_dwThreadId)」 で、スレッドを生成し、そちらで、 if(GetAsyncKeyState(VK_UP)&0x8000) ではキーが取得できるのに、 GetKeyboardState(diks) if(diks[VK_UP] & 0x80) ではキーが取得できません。 どうも、メッセージキューやらが原因みたいですが、理屈がイマイチわかりません。 解決策や問題点など、教えていただけると幸いです
626 :
626 :2009/05/22(金) 00:14:01
追記です。 そもそもGetKeyboardState()はメッセージキューに溜まったものを見るものであって、 新しく生成したスレッドでは、肝心のメッセージを取得することができない、、、 というあたりまではなんとなく理解できました ちなみにやりたいことはキー情報の一括取得(できればリアルタイムの)です。 (GetAsyncKeyState()では1つ1つしか取れないので・・・ 引き続き、解決策などありましたら、お願いします
627 :
626 :2009/05/22(金) 01:06:46
生成したスレッドの方で、 // Threadのインプットのアタッチ int targetThread, selfThread; targetThread = GetWindowThreadProcessId(GetForegroundWindow(), NULL); selfThread = GetCurrentThreadId(); AttachThreadInput(selfThread, targetThread, TRUE ); /*===== メインループ =====*/ // Threadを切り離す AttachThreadInput(selfThread, targetThread, FALSE ); とすれば、GetKeyboardState()でも一応取得できました。 荒療治な気がしますが・・・ もっと良い方法などありましたら、お願いします
>>617 適当なsystemcallを行い、前後でCPUのtimestampでも読めば、
最も軽い場合については、調べられる。
>>625 DirectInputを使うとか。
>>627 GetKeyboardState()が使用する入力情報は、スレッドごとにある。
AttachThreadInput()はそれを共有させるためのAPIなので、その目的なら
それが一番適切な方法。
ただ、フォアグラウンドウインドウにAttachしてるのは間違いじゃないか?
GetAsyncKeyState()は自分のプロセスが非アクティブでもキー情報を取得できるAPI。
自プロセスの別スレッドでキー入力を拾う目的で使うのは、使えないことはないが
自分がアクティブかどうかの確認が必要で面倒。
630 :
626 :2009/05/22(金) 04:59:32
>>628 DirectInputは同じような理由で取得できず...(・ω・
>>629 問題なく動いてるんで今の形(フォアグラウンド)で放置してたんですが、
ウインドウハンドルって引数以外で取得できるんでしょうか
>>630 GetWindowThreadProcessIdもGetForegroundWindowもいらない。
beginthreadexを呼んだスレッドで、そのままAttachするだけ。
そもそも、自分のウインドウを取得するのにGetForegroundWindowを
使うこと自体おかしい。
アプリケーションを起動したら必ずフォアグラウンドになるわけではないし。
632 :
626 :2009/05/22(金) 15:13:54
確かにかなり回りくどいことしてました。
ただ、Attachの処理は生成処理の直下で一度だけ呼び出しても機能しなかったので、
beginthreadexを呼んだスレッドID(MainThreadId)だけをセーブして、
>>627 と同じ場所で「AttachThreadInput(CurrentThreadId, MainThreadId, TRUE );」という形にまとめました。
新しく作成されたスレッドはGUI関連のAPIを呼び出すまでメッセージキュー等が 作成されないから、スレッド作成直後だと失敗するね。 新しいスレッドでウインドウを持っているならウインドウ作成後、ウインドウが なければPeekMessageの空呼び出しの後でAttachがいいかな。
634 :
??? :2009/05/22(金) 16:58:17
アセンブリ言語によるプログラミングで、1+2+3+・・・・+10と、1から10までの足し算をするプログラムはどのようなものになりますか? 16進数表現です。
まずは正しいスレッドを探すことからだな
質問です。 constで定義されている、読み込み専用の変数に対して 複数のスレッドがアクセスするとき、同期(クリティカルセクションなど)は 必要ありますか?
よっぽど変なハードウェアでない限り 要りません。
638 :
デフォルトの名無しさん :2009/06/10(水) 19:52:05
volatileで十分w
volatile使うやつは情弱
WindowsXP、VC2008EEの環境で作っています。
>>636 の質問とかぶるのですが、1つのコンテナを複数のスレッドからイテレータでアクセス(読み込みのみで書き込みはない)しています。
実行時にイテレータを使った部分(直接使用しているのはSTL)でエラーが出て強制終了になってしまいます。
試しにスレッドを1つにしたらエラーは出ませんでした。
どういった原因が考えられるでしょうか?
そのSTL実装がスレッドセーフじゃないんでしょ。 機能としての読み込みであっても、内部で書き込みしていて競合する場合もあるだろう。 アトミックなところまでスレッドセーフが保証できないならロックすべき。
>>641 なるほど・・。
マルチスレッドは難しいですね。
>>640 単純に興味本位なんだが、const_iterator でも駄目なの?
最近マルチスレッド環境下でスレッド毎にプールを持つ malloc() 実装がよくあるよね? 諸々の事情でそれが使 えない場合、アプリ側で出来る事ってある? OO 的に小さなオブジェクトを生成/破棄するんだけど、 スレッドを跨って破棄を委譲するケースもあるんだ。で も、単純にメモリ管理スレッド作っても過去の効率の悪 い malloc() 実装の焼き直しみたいになって多分効率悪 いと思うんだよね…。
アプリ側でそういう実装をやってるのはあっても動作環境側でそんな実装やってるの在るか? 複数のプール持つ実装はあるだろうけどスレッド固有になるような実装してたらそれこそスレッド跨げないし
jemallocは自分が割り当てられたarenaをヒープのメタデータにつっこんでおいてfree時にはそこから解放するようになってる 割り当てはそれこそぽんぽん次のarenaをTLDに結ぶけどさ そうでもしなきゃFreeBSDのデフォルトになれてない 完全に一切ロックせずスレッド固有のヒープにするなんてのはアプリ内の実装でなきゃ出来んよ
いやだからそのアプロ側でどうすんの? ってのを聞いてるわけで…。
一体何を心配して居るんだお前は?
小さいメモリ大量なら、固定長のバッファをリンクリストかなんかに つないでおいて、利用すればいいじゃん。malloc, freeよか速い だろ。
>>644 mallocにしてはやりすぎじゃない?
C++のallocatorならそういうのもあると思う。
とりあえず何も考えず素直に作って問題が出たら詳細に 考えることにするよ。一応アロケータ的なインタフェイ ス挟んでるから後からでもなんとかなると思う。 malloc/free に時間かかってる/かかってないの判定と かは gprof 辺りで大丈夫なんだっけ?
>>652 一応gprofでも判らなくもないと思う。呼び出し回数は記録されないけどね。
使える環境なら、vtuneみたいなツールを使う方が(当然)判りやすい。
pthreadで、デタッチ状態のスレッドをポコポコつくったりしてるとき 生成したスレッドのうち今何個生きているかを知りたいんだけど pthread_hogehoge() で何か知れるような手段用意されてたっけ?
655 :
デフォルトの名無しさん :2009/08/04(火) 11:52:30
マルスレage
無いんじゃない?atomicなカウンタでも使えばいいじゃん。
>>656 もしそういうカウンタがもうあるなら再車輪せずに済むかな、と。
>>658 pstreeとかのソース読んだからまあ大体のことはできるんだけど
そうか、管理しないことをウリにしてんのか。仕方ないなぁ。
スレッド管理はOS任せか〜。そりゃそうだよなぁ。
Javaで複数のインスタンスのAというメソッドに同期をかけたい場合は、 どうすればよいのでしょうか?
>>660 同期は(メソッドにかけるものじゃなくて)メソッドが
アクセスするリソース(メモリやディスク)にかけるものだよ。
あと「同期」はスレッド間でイベントの発生待ち&発生通知を
実現する場合に使われる単語。もしもスレッド間で
(メソッドを通した)リソースへのアクセスの競合を避けるのが
目的なら、「排他制御(あるいはロック)」という単語を使うのが適切。
で、質問が(後者の)排他制御を実現する場合に関するもとすれば、
各インスタンスのメソッドAで(アクセスしたいリソースへの)
排他制御を実装するコードを単純に書けばいい、というのがレスになる。
もしも各インスタンスのクラスが同一ではないため、複数クラスで
メソッドのコードを変更するのはプログラム構造が複雑になると
考えているなら、たとえば以下のようなヒントが参考になるかもしれない。
・コールバック機構を利用して並行処理時に発生するバグを防止する
http://japan.internet.com/developer/20050927/25.html
>>661 ご回答ありがとうございます。
プロセス起動時の初期処理用メソッド(DBからマスタを取得し、キャッシュする)に同期をかけたいと思っていました。
お返事どおり、メソッドではなく、リソース(オブジェクト)に対して、ロックをかけるのが正しいですね。
キャッシュクラスをシングルトンで実装し、同期化をさせることにします。
663 :
デフォルトの名無しさん :2009/08/11(火) 00:33:30
メソッドにsynchronizedを付けると、同一インスタンスで1つのスレッドしか実行できないということですか? 複数インスタンスあれば、実行できてしまうのでしょうか?
できてしまいます
staticメソッドなら大丈夫。 synchronized(Hoge.class) とか
>>665 > staticメソッドなら大丈夫。
> synchronized(Hoge.class) とか
そこまで書くならstaticメソッドじゃなくてもいいじゃん
667 :
デフォルトの名無しさん :2009/08/16(日) 00:34:07
マルチスレッド環境でマスタデータをDBからとってきて、HashMapかListなどに持たせるのは 問題ないのでしょうか? 基本的にJavaプロセスを起動している間にマスタデータが変更されることはない環境です。
668 :
デフォルトの名無しさん :2009/08/16(日) 00:34:56
667です。 データを持たせるHashMapかListはクラス変数で持たせたいのですが。
情報不足 どういう問題がありえると思ってるんだ?
670 :
デフォルトの名無しさん :2009/08/16(日) 01:02:48
すみません。 HashMapとかListに数千件というマスタ情報を持たせるのがおかしくないのかという点と、 HashMapやListにデータを追加するときはロックをかけますが、データを取得するときは ロックをかけなくても問題ないかを知りたいです。
>>670 ハッシュなんてもんはメモリが許すなら数万件程度は入る事を前提で作るんだが
>>670 (すでに別の方法で同期済み等で) 追加と取得が同時には起きないと判っているなら、取得同士の間のロックは不要
追加と取得が同時に起きるかもしれないなら、取得にもロックは必要
通信とかどうでもいいから普通にマルチコアに特化したライブラリってないのさ?
つintel TBB
>>673 スレッド間通信が無くても役に立つマルチスレッドアプリとは何者?
ブルートフォースとか
pthreadでPSで表示したときのスレッド名を変える方法ってありますか?
ないんじゃない?
PR_SET_NAMEすればいいんじゃない?
Cでマルチスレッドのプログラミングで ふたつのスレッドの時間的な同期をとって 同時に同じファイルを開くにはどのように書けばよいですか
685 :
682 :2009/08/28(金) 16:18:17
>>681 2つのスレッドから共通のモジュールを介してファイルにアクセスするようにしてはどうですか
2つのスレッドからは1つのファイルを開いているように見せつつ,
そのアクセス(読み書き)先の実体であるモジュールの中で排他制御するんです
対象OSにどういった同期手段が用意されているかによる どの程度同時性を求めるかにもよるし、それはつまり何のために同時でなきゃならないのかにもよる
>>681 日本語の文章がちゃんと書けない人はプログラミングも出来ない。
by 竹内
>>686 これ、日本語が致命的に下手なだけで、要点は
ただ排他制御したいってことだろ
時間的な同期を取るってんだから、「同時」の意味が違うかもしれんぞ
日本語が下手ではなく、 頭の中で思考の同期が取れてないのでは。
排他制御しないって意味かもしれんぞ
まぁ、
>>681 がマルチスレッドでプログラミングすべきでないことだけは間違いないな…
>>681 同時に開く保証はできない。
「ほぼ同じ頃に開くことができるかもしれない」が限度
2スレッドをイベント待ちにしてから、同時に起こすのかと思った。
マルチスレッドプログラムでのよくある落とし穴をまとめたサイトってどこかにない?
シングルはあるよな
まぁ「プログラムなんてとりあえず動けばいいや」と考えている奴は大抵マルチスレッド関連でバグ出してハマるしな。
>>698 そういうのは未だ救いようがあるが自分の痛さに気づいていない
プログラマーは救いようが無い。
700 :
696 :2009/08/29(土) 11:39:02
よく見たらゴミ記事であるな。 参考にしないほうが良い。スマヌ Orz
701 :
696 :2009/08/29(土) 11:47:41
ゴミ記事って言うのは酷すぎた。。 前提知識のない初心者が見ると混乱すると言うのが正しい。
冒頭の四行くらいで日本語も問題切り分けも怪しく感じたから流し読みしたけど どうでもよさそうな記事だった
シングルトン実装から始まって愚駄ぐだになって終わってると。
>>696 の記事の二重チェックロックなんだけど
if (_Value == null) {
lock (ValueLock) {
if (_Value == null) {
A temp = new A();
Thread.MemoryBarrier();
_Value = temp;
}
}
}
Return _Value;
これだと_Valueが更新される前にlockから抜ける可能性ない?
Thread.MemoryBarrier()するのは_Value = temp;の後じゃないの?
_Valueの代入はlockの中にあるから、_Valueが更新される前にlockを抜けるわけはない 第2のスレッドがやってきて外側のif(_Value==null)を見たときに、 もし_Valueがまだnullならlockに引っかかるから最初のスレッドが更新を完全に終えるまで待たされるので問題ない (lock/unlock自体がメモリバリアになる) 問題は_Valueがすでにnullでなかった場合、_ Valueは新しいオブジェクトを指しているけれども_Valueの中のフィールドはまだ更新されてない、という事態が起きうる (メモリの書き込み順序は勝手に並び替えられるので) それを防ぐためにメモリバリアを挟んで、_Valueが更新されるよりも前に_Valueの中身が更新されることを保証している
_Valueが更新されるよりも前に_Valueが参照されないことを保証している
_Valueへのアクセスは同期されてないから、lock中で_Valueが更新された直後から 他スレッドからAが使えるようになる。 でも Aの構築 _Valueの更新 Aの構築の結果がAのフィールドに反映される となる可能性があり、不完全な状態のAが使われる可能性がある。 だからAをnewした後にThread.MemoryBarrier()してから_Valueに代入する。 _Valueへの代入はlockを抜ける段階で保証される。 ということか。 勉強になった、ありがとう。
709 :
デフォルトの名無しさん :2009/09/01(火) 20:32:30
クアッドコアを使った並列処理を MFCでのマルチスレッドでやろうとしておりますが、 シングルコアのときと同じマルチスレッドのプログラムでも 4つのコアを利用した並列処理になるんでしょうか?
なるよ
711 :
デフォルトの名無しさん :2009/09/01(火) 20:38:55
erlang
>>709 MFCには詳しくないけどシングルコアで問題なく動いてたMTセーフのつもりの
プログラムがマルチコアにもってくと異常動作することはそれなりにあるん
じゃないの?int型への代入・参照を非同期でやってたりするプログラムだと。
>>713 何故int? 64bit整数ならわからんでもないけど。
つーかそんなことを質問してるわけじゃねーし。 言ってみたかっただけだろ。
intでもread-modify-writeはatomicじゃないぞx86は(も)
>>709 なる。OSネイティブのスレッドは、明示的に指定しない限り、複数のコアに分散される。
とは言え、排他制御が適切でないと、各コアを有効に利用できないけど。
>>716 いや、それだったらそもそもデータ型問わんのでは。
いやいや、おまいら、それ以前にそれはスレッドセーフと呼ばないのでは。
>>718 64bitなら、と言ってるから、マシンワードならアトミックと思ってるのかなと思った
volatile
volatileがどうかしたか?
vottakle
明白な答えが、ここで出せるわけ無いんだから。 あなたが欲しいのは同意なんじゃないの?だから荒れる。
>>724 独り言が言いたいだけだ、とかでないなら
最低限アンカーくらい書いたら?
∧∧ ヽ(・ω・)/ ズコー \(.\ ノ 、ハ,,、  ̄  ̄
>>696 いまひとつ怪しい記事だな。
だいたい今の.NETじゃ前提が変わりすぎてて、役にたたないどころか害のが多い気がするし。
>>720 64bitを持ち出したのは、32bitマシン(あるいは32bitモード)だと、単一の書き込み/読み出しでも競合すると値が壊れる可能性があるから。
(最初の32bitが書き込み前の、次の32bitが書き込み後の値を読み出す可能性がある)
マシンワード以下なら、順序が入れ替わることはあっても値が壊れることはないと思ってるんだけど、それもあてにならない?
あと、x86系だと、ワード境界をまたぐ読み書きがどうなるかがよくわからない。
>>729 >マシンワード以下なら、順序が入れ替わることはあっても値が壊れることはないと思ってるんだけど、それもあてにならない?
w
The Art of Multiprocessor Programming 糞本だなぁ
volatile
volatile変数へのアクセスのアトミック性は、non-volatileな変数へのアクセスと同じ だから、この流れにvolatileは何の関係も無いよ
>>706 読み取り側ではメモリバリアはいらないの?
_Valueの値を読み込む前にその指す先の値を読み込むのは不可能だから メモリバリアがなくても読み込み順序は入れ替わらないはずで要らない・・・んじゃないかなたぶん
volatileの話をするときは、C/C++なのかJava/C#(CLI)なのかをはっきりさせろ。 それぞれのvolatileの意味はまるっきり別なんだからな。
そうか、やっぱりだめか 例の記事は今見直したらvolatileが付いてるな なるほど
それはメモりバリアかvolatileどっちかって話だから意味ないよ
C++っていつまでAtomicIntegerとかないわけ? ふざけてないか?いい加減にしろ
と言われても今年決まる新標準には採用されてるし 一企業や一個人に独占されてる言語と比べるなよ
>>744 C++0xは2012年まで延期でしょ
今すごい揉めてるでしょ
つーかC++使うならそのくらいはライブラリかAPIか自力で何とかできないと 結局他でつまづく
ちょっと来週あたり C++のatomic実装投下するから誰か100% 厳密に正しいか判断できる人いますか?
投下してから聞け。
現行C++ + Boost + TBBで組んでおけば、C++0xの時代になっても スムーズに移行できるんじゃないかな
最近はC++の仕事が減ってC#とCばっかりになったお
gccだとvolatileは付けても付けなくても 効果ないんだね
SomeType() = default; って奴を普通のC++に直すと どうやってかけばいいの?
>>753 // SomeType() = default;
gccでもvolatile付けたら本来のvolatileの効果はあるだろ
ちゃんと実装されているマルチスレッドアプリってあるのだろうか。 このスレ見てるとある特定の条件下でたまたま運良く動いているアプリばかりじゃないかと思ってしまう
たまたまでもバグが入り込まなかったのならすばらしいことです
このスレだけが世界のすべてだと想うなかれ
引っ掛かりやすい問題点は多々あるが、ちゃんと分かってくれば安全に書ける ただ、その「分かってくる」までのハードルがそれなりに高いから、手を出せる開発者 もなかなか増えないし、MTに対応することで恩恵の得られるアプリも少ないから、 MT対応アプリそのものがなかなか増えない訳だが IntelもMTのフレームワークで金取ってる余裕ねーだろうにと思う(MSあたりは別に どっちでもいいんだろうが)
>>752 は
const volatile int x;
の説明も出来無さそうだな。
ああ、const volatileの意味がすんなり理解できるかどうかはいいテストかもなw
それがconst volatile autoな変数なら私には理解できません。
C++0xのautoってcvとか*とか&とか付けられるんだろうか
>>760 最適化されないRead Onlyな変数以外に何かの意味があるのか?
別に最適化されない訳でもないが
>>758 日本のマルチスレッドプログラム界の縮図がこのスレだと思っておりますが。
ここには「実戦ではまだまだ書けませんが」って人もかなりいると思われ
>>767 そういうヤツは時間の問題でちゃんと書けるようになる。
そんな自覚のないヤツほどマルチスレッドを使いたがる。
マルチスレッドってコンパイラの最適化やCPUの命令の実行順序まで いちいち気にしていないとまともなプログラムは作れないって事ですか?
いいえ mutexやcondvarの使い方を知っていれば問題ありません
mutexは遅いからイヤだ、などと言い出すから話がややこしくなるだけです
condvar?
条件変数 win32ならイベントオブジェクトか何か・・・・・・特定の出来事を待って寝ているスレッドを起こすメカニズム
スレッド間通信そのものがボトルネックになるような場合は、mutexなんか使って
られないから
>>770 は真に近い
スレッド間通信のコストが無視できる場合は、
>>770 は偽に近い
>>769 そのブログのおっさんって何者なんですか?
>>770 単純に動くものを作りたいなら、そこまでローレイヤーのことを考える必要はない。
が、
プログラムのパフォーマンスを上げたかったりするんだったら、
考える必要が絶対に出てくる。
「まともなプログラム」==「メジャーなソフトウェア」って認識なら、
言う通り、そこまで考えないとまともなプログラムは作れない
>>770 適当に作ってはったりかます方が金になるから
きちんとモノ作りする奴は馬鹿を見ると思った方がいいぞ
mutexの速度が気になるようなプログラムなんて組んだことないぜ 速度より安定性重視な俺はプロだって周りかよく言われます
必要無いならそれでいい カーネルやドライバを書いてるような連中はそういう訳にはいかない 科学技術計算やゲームエンジンを書いてるような連中もな
正しく動くものできっちり金を取った後、 また高速化するたびにきっちり金を取るのはプロだと思う。
最初からある程度高速じゃないと金の取れない業種もあるけどな
そういうプロが幅を利かせるから日本のIT業界はいつまでたっても土方っていわれるんだろな
よく知らんけど海外でもそういう手合いはいるんじゃね? 変に胸張って「俺らこそがプロ」みたいな顔をしてるかは別として Googleみたいなとこのプロはそういう手合いとは思えないしな
>>780 に同意する。
いかにmutexの回数やクリティカルセクションの範囲を減らすかに設計能力を注ぐ。
要は、スレッド間の同期を減らし、スレッドの並列度を上げることが目的。
ただし、(
>>770 の言う)コンパイラの最適化やCPUの実行順序までは考えない。
(
>>782 の言う)正しく動くものを作ることを最優先する。
マルチスレッディングと、その最適化には、高度に抽象化された思考能力と設計技術が要求される。
(
>>778 の言う)ローレイヤのことを気にした(言い換えると、ローレイヤの振舞いを前提にした)
スレッディングのロジックを組むということは、プラットフォーム依存な設計であるということ。
(
>>781 の例であれば)科学技術計算ならUNIXからWindowsへ、ゲームエンジンならPS3からXBoxへ
移植するたびにロジックの再設計が必要になる。
もしかすると自分が知らないだけで、(意図的に?)そういうローレイヤ前提な設計をして、
移植の度に利益を得るという(
>>778 ,779,781のような)世界があるのかもしれない。
ただ、それは(
>>784 の言う)土方仕事と呼ばれる日本のIT業界の縮図そのものであると思う。
例外があるとすれば、カーネルの、しかもスレッドスケジューラやmutexそのものを実装する
コアなデベロッパに限る。彼らはハード(CPU)の能力を最大限に生かす基盤を作る人達だから。
いや、普通に移植性の高いlock-free queueとか書けるから。
ハードリアルタイムやったことないやつって性能無視の安定指向が強いよな
マシンパワーの需要と供給の比がカツカツかトントンか余りまくりかで全然違うからな それを無視して、どれか一つのパラダイムだけで語る奴は問題がある
CompareAndSetとか、既に どの開発環境でもインラインアセンブラ関数 用意されてるから、CPU変わっても大した話 じゃないよ
ところでお前らlock-free queue とか朝飯前なんだよな? なぁどうなんだ?
>>789 ですよねー周りの見えない技術者ほど使えない物はないです
物理シミュだと、精度が要るところは安定性重視でそうでないところはピーク性能重視。 マシンパワーの配分はジョブによって違うから動的に。
>>791 Javaのマルチスレッド本にlock-free queueの実装が載ってたんだが。
「どうやってlock-freeを実現しているのか」は何とか理解できたが、
自分で一から書けるか、と聞かれると胸を張って「No!」と答えるしかない。
>>791 俺は今書いてる
書いたらここにうpして
虐めて貰おう
要求条件によって実装も細かく変わるからなぁ、lock-freeは
IntelのMathKernelLibraryはやばい あれこそプロの仕業だ
>>781 のような世界では
LockFree程度じゃ満足されないぞ。
RCUとかを使ってCasFreeにして、
メモリバリア(バスロック)を減らさないと充分ではないと言われるんだ。
メモリバリアがあると、シングルコアでもバスクロックで数クロックを消費するが
これが他のコアのCASが原因でも起こるわけだからな。
>>797 MKLは、OpenMP対応しているから勿論OpenMPで並列実行させてもいいのだけれど。
意外なことに、MKLを使ったプロセスを複数同時実行させてもリニアリティが高いのが凄い。
>>798 lock-freeが要求によって実装がまちまち、ってのはそういうのも含めたつもり
CASは使わないがメモリモデルや要件的にRCUも不要な場合とか、色々あるからなぁ
ロック中に、割込処理みたいなコンテキストスイッチしない人が飛び込んできたら デッドロックしちゃうけど、一般的にこういうのはどうやって回避する?
飛び込ませないとか
割り込み処理の中で何かをロックするというのはやめようよ
ロックって他のスレッドをロックしなければコスト低いのな 特定のクラスの関連のない処理を同じロックオブジェクト使ってすげー遅かったのが 処理ごとに別のロックオブジェクト使うようにしたら殆どコストが無くなった 当たり前だよな・・・
>>805 では聞くが、それは本当にロックする必要があったのか?w
あるし
ロックの粒度は可能な限り小さくする派です でもそれ以前になるべくロックしないでいいように設計します
それが言いたかったんです けど小さいロックを連続でするくらいなら少し大きなロックを1回の方が効率いい時もある
以前ねえ、ロックの粒度を細かくしていったら 滅多に競合しないのに、オブジェクト毎に計数千個のロックが作られる事態になったことがある。 (rwlockのエミュレーションで、Win32でやってみたらHANDLEの使用量が跳ね上がったり) で、こういう場合はどうするのが妥当? 1) そのまま数千個使う 2) ハッシュ等でロックを減らす 3) がんばってrease-releaseする形にする まあ3)が一番まともかと思うんだけど CASとかを使ってうまく解決できるのかな。
>>809 > 少し大きなロックを1回の方が効率いい時もある
ロジック的に必須な少し大きなロックを洗い出して、ち
まちま小さなロックを作らないように設計するかな。
大抵他のものと絡めて排他する必要が多いから、部品単
位にロックを用意することはあまり無い。
「粒度を小さくする」っていうのはその上でロック期間
が短くなるようにすることだと思ってる。
compare_exchange_strong compare_exchange_weak の違いってなんなんですか?
813 :
801 :2009/09/08(火) 01:50:20
割り込み中に重たい処理をやりたくないから、割り込みじゃない人に 重い処理をやらせようと思って、タスクキューみたいなのをこしらえて せっかくだから処理を全部タスクキューにやらせようと思ったのよ そしたらキューにタスクを積む処理で詰んだ
頑張って、「キューに追加/取り出しの処理」をlock-freeにするんだ。 場合によってはキューのデータ構造から書き直して、な。
単純にタスクキュー触る間だけ割り込み禁止に・・・ 処理させたいタスクに対応するビットフラグ立てるだけでもよくない?
割り込みで lock-free キューに詰んで、表側で適当な ディスパッチタイミングで必要な処理を起こす、ってい うのなら出来そう。キューの保持数が 0 → 1 のタイミ ングで通知を送って…とかだと詰みそう。
lock-free のほうが簡単では? たとえば、A B Cの処理は衝突無し、順序関係無しだったら 3つのスレッドのキューに渡すだけでしょ? なんで、マルチスレッドは、排他制御や、待ちの方が発展したのか不明。こっちの方が難しいだろ。
lock-freeって、実際にどういうアトミック命令を組み合わせて実装すんだ それっぽい紹介サイトがみつからねぇ・・・
コンペア・アンド・スワップを使わないと 処理がうまくいかないケースを知りたい。
なにこれむずい
>>820 俺は逆にCAS無しで上手くいくケースを教えて欲しい
>>822 以下の方法なら、これなら(フラグの)ビットは1個あれば済むよ。
実際にUNIXのデバイスドライバ(STREAMS)で実装した。
タスクキューを複数のサービススレッドが共有する。
割り込み処理ではタスクキューにイベントを入れてフラグを立てる。
複数のサービススレッドが一斉に起きて、最初にスケジュールされた
スレッドだけがイベント取り出しに成功しフラグを落とす。
他のスレッドはタスクキュー空(から)なので、再び待ち状態に入る。
割禁の範囲はタスクキューとフラグを触る時だけ。
UNIXでハードなリアルタイム性は要求されないから、可能な手法だけどね。
ぜんぜん常識じゃないよ。 Mac OS はいい意味で、ようやっとるなと思う。
まだ途中までしか読んでないが 完全自動じゃないけど IOCPでの、CPU数にあわせた同時実行数自動決定が、似たような仕組みなんじゃないか。 プールするスレッド数は(一般にCPU*2とか言われているが)自由なんだし。 ただ、ライブラリやフレームワークがそれを利用するように作られているか、といえば 答えは明らかにノーだけどね。 当然、言語仕様なんか触ってないから、 一つ一つのジョブは自分で切り分ける必要があるし、 手間は段違いだろうね。
>>826 しかし、依存性のないブロックに分割するのは手作業なので、
その記事で絶賛されているほど楽になった感じはしないけどな。
結局自分でワーカースレッドを起こさなくてもいいってだけなので
windowsでいうと、ファイバを利用したスケジューリング用のライブラリがあって
それを利用してコードを書いてるような感じだ。
斜め読みだけどOpenMPの発展系といった感じかな? MSだとParallel LINQに近い気がする。
>>823 819の預金処理は、同時にメモリにアクセスすることは無いだろうが。
口座番号 % n ごとに処理する。 それぞれのスレッドは独立していて
各スレッドが順次処理している限り、衝突など無い。
>>828 依存性を判断してブロックに分割すれば、あとはフレームワークまかせなのだから、
設計者にとっては、かなり負担を減らせるのでは。Apple絶賛はさておき。
判断そのものの自動化は、副作用が前提な手続き型言語では非常に困難だから、
データフロー型言語が一般化する時代にならなければ実現しないと思われ。
今の流行ならHaskellやF#みたいな関数型言語が近い位置にいる。
あと、GUIライブラリとの連動が考慮されている点も設計者にとっては大きいね。
画像編集や3DCGみたいな分野で、Macの勢力が一気に増大する要因になるかも。
833 :
824 :2009/09/08(火) 19:15:59
>>832 (
>>824 の話は)割禁が使えるUNIXデバドラでの実装だから、
割禁が使えないときのことは分からない。
というか、割禁がまったく使用禁止な世界(ドライバ開発?)というのが想像つかないんだけど。
サービススレッドは定期的に(Lock-Freeな)キューをのぞきにいくのかな。
それほどレスポンス性能にシビアな世界で、ポーリング方式を採用するのは逆効果な気がする。
Lock-free/Wait-freeには全く詳しくないんだが、割禁が使えない世界というのを、
もしよければ教えてくれないか?
>>819 >> 預金残高の書き換え処理をn並列で行いたいなら、n個Wait-freeキューを作り、
「Wait-freeキューを作り」の中で、アトミック命令が使われているんだが
そういう意味では無いのかな。
単に「自前で実装する必要があるか否か」という意味なら
いくらでも「○○は不要」なものがあるだろう。
>>833 「割り込み処理」というのはハード的にはまあ確かに割り込みだが
処理内容的には、「別スレッドからの非同期な処理要求を処理するか」に近い。
つまり、割り込み禁止とは「排他ロックを獲得してから処理を開始する」
ということと同様になる。
実際、あまりに長時間割り込みを禁止していると割り込み要求が破棄されるものがあったと思うが
これは、別スレッドからのtrylock要求が規定に達したのであきらめる、というのと同じかと思う。
だから何ってほどでもないけどね。
実際には、「割り込み処理の入り口でロックを獲得」という
(やってはいけない)やり方をせずに済むわけだから。
ただし、通常は競合が無い限りCAS2回で済むロックの獲得/解放の変わりに
システムコールにつながるであろう割り込み禁止処理を入れるというのは
普通のユーザーアプリケーションにとっては
コストが大きすぎて採用できないだろうけどね。
(x86のcli/stiも特権命令だしね)
>>834 Wait-free関連のどんなライブラリも不要だろ。
このケースだとスレッドをn個つくって、
各スレッドは、渡された処理を順にこなすだけ。
どこにも衝突するところは無い。
( 同銀行間での送金処理があればぶつかるが。)
要するに、メモリ共有のある部分を並列処理しなければ、何の問題も出ないって事だな。 メモリ共有しながら並列処理しなければ、出来ない(パフォーマンスが落ちる) ケースってどんなのがあるの? アルゴリズムの工夫で解消無理なの?
>>835 そのスレッドに処理を渡す時点で、CASが必要だと思うが。
>>837 そうか。
処理を渡す側が、マルチスレッドの場合があるか。 ATMは日本全国にあるからね。
そりゃ、同期の必要が無い処理なら、CASもロックも不要。 当たり前すぎて笑えてくる。
口座番号でスレッドに分けて、ATM毎に格納するメモリを確保しておいて メモリの先頭から、順に処理すれば衝突は出ない。 後ろの番地のATMは番が回ってきにくいけど。 そこでさらにATM番号でスレッド分けて、一スレッドで処理するATM数を1000個とかにすればいいだろう。
お前はスレッド(口座)に対するディスパッチに、同期処理が必要無いとでも思っているのか。 さては、ATMでの出金だけで、振込みとかやったことないだろ。
で、まあ、実際のところ、処理によってはCASが不要なものも確かにあるよ。
少し前に書いたけど、RCUとか使ってね。
(
>>819 の書き込みがあまりにもアホっぽいから突っ込まれてるだけでね)
ただ、RCUはそれはそれで破棄のタイミングが問題になるし
破棄するものをキューに入れるとかする場合にはそっちでCASが必要になったりとか
適用できる範囲が限定されるんだけどね。
口座間の送金処理ありの場合に、同期処理を不要にするアルゴリズムが存在するか考えてみる。
とりあえず、RCU的な使い方 いわゆる「volatileで充分」な処理は 「更新の競合が絶対に起こらない」というのが大前提だから。 更新が競合する可能性がある場合は、必ずCASが必要になるはず。
846 :
843 :2009/09/08(火) 21:11:45
2つ以上の口座から、一度に入金が来る場合が問題か。 841の様に、入金用に、口座毎にメモリを確保しておき、先頭から処理すれば衝突避けられる。 しかし、口座数×口座数だけのメモリが必要になり実用的でなさそう。
トランザクショナルメモリないと こんなのCASだけあっても意味ねージャン
ドライバ開発で、割り込みハンドラでさわるリソースが、 通常コンテキストで触るリソースと競合するなら、 割り込み禁止以外ないと思ってたけど、そうでない 一般的なやり方があるなら教えてほしいのぉ。 マルチコアだと、単一CPUの割り込み禁止だけでは 不十分でspin_lockとかいったりするが。
>>848 割込ハンドラは割込スレッドを起床させるだけ。
割込スレッドと通常コンテキストとの間の排他は優先度継承付きmutexで行なう。
てな感じで
850 :
824 :2009/09/08(火) 23:27:18
>>834 レスありがとうございます。
非同期な処理要求がガンガン発生するケースについては分かりました。
ただ、もし処理要求がまったく発生していないアイドル状態の時、
サービススレッドは処理要求の発生をどのように待っているのでしょうか?
たとえば、以下のようなループを組むとか考えたのですが、
while (queue.empty) yield(); /* yield()は他のスレッドへ制御を移す関数 */
システムはアイドル状態にもかかわらず、スレッドがCPUを浪費してしまいます。
Wait-freeライブラリ(?)の中で、新たな処理要求が発生するまで
サービススレッドをwaitさせてくれるような仕掛けが実装されているのでしょうか?
851 :
824 :2009/09/08(火) 23:31:28
>>849 え、ハード割り込みの延長でmutexを呼ぶのですか?
もし競合していたら割り込みがwaitする(?!)ことになるので、
一般的なドライバ開発ではあり得ないと思うのですが。
>>851 だから「優先度継承付き」と言っているではないか。
Solaris Internalとかを読むべし。
>>852 優先度継承したら、割り込みコンテキストぬけて通常コンテキストに
スイッチするん?Solarisは。んなことはないと思うが。
割り込みスレッドを起床するだけというのは普通だと思うが、
割り込みスレッドを起床している間は、通常大本のハードの
割り込みは禁止するよね。禁止するときにレジスタアクセスとか
あってwaitいったりすると、やっぱり通常コンテキストと
割り込みコンテキストで排他は必要になると思うのだが。
>>853 > 優先度継承したら、割り込みコンテキストぬけて通常コンテキストに
> スイッチするん?Solarisは。んなことはないと思うが。
割込スレッドがmutexでブロックしたら、mutexの競合相手(これは通常コンテキストかもしれない)にコンテキストスイッチして、
mutexの排他区間を抜けさせる。
そしたら元の割込スレッドの処理を続行することができるよね。
>>854 、
>>855 だから、割り込みスレッドと、割り込みコンテキストはちゃうっつーのに。
2chで何かを期待した俺がアフォだったよ。
857 :
824 :2009/09/09(水) 01:56:56
>>852 Solarisは専門外なので書籍は持っておらず、Sunのサイトで
Writing Device Drivers という文書を斜め読みしてみました。
以下は第8章 Interrupt Handlers の節 Interrupt Handler Overview
からの引用です。
・
http://docs.sun.com/app/docs/doc/816-4854/interrupt-15678?l=ja&a=view .... The job of the interrupt handler is to service the device and stop the device from interrupting. When the interrupt handler returns, the CPU resumes the work it was doing before the interrupt occurred.
ここには「割込ハンドラがデバイスからの割込を禁止し(stop)、ハンドラがリターンすると
CPUは以前の処理を再開(resume)する」とあります。これは割禁を指していると思うのですが....?
Solarisの場合には、デバイス構造体に「特殊な」優先度付きmutexが含まれているみたいですね。
割込ハンドラが、この特殊なmutexを操作することで割禁制御を実現しているように推測できます。
ただし、この優先度はハード割込の優先度であって、スレッド実行の優先度ではありません。
また、このmutexの操作対象はデバイス(の割込)であって、割込ハンドラとサービススレッドとの
間にあるリソースでもありません。
スレッド間の排他制御に用いられる「一般的な」優先度継承付きmutexと混同していませんか?
858 :
824 :2009/09/09(水) 02:22:51
>>854 たとえコンテクストスイッチしたとしても、その間に再度ハード割り込みが
次々に入ったらどうなりますか?それを避けるのが割禁の役目だと思います。
>>855 「割り込みスレッド」というブラックボックスな言葉を鵜呑みにしていませんか?
そのwikipediaからの引用部分の前段には、割り込みハンドラが第1レベルと
第2レベルの2つの部分に別れているとあります。Solarisの場合であれば、
カーネル(デバイス)内にあるのが第1レベルであり、その「実行中は割禁」される。
また、デベロッパが作る割り込みハンドラが第2レベルであり、
一般的には「割り込みスレッド」と呼ばれている、と自分は解釈しています。
結局、割り込みスレッド方式であっても「デバイスドライバにおいては、
割禁は避けられない」と思うのですが、間違っていますか?
Solarisの場合には、特殊なデバイスmutexによって割禁制御を抽象化しているから、
デベロッパは割禁を意識せずにデバドラを開発できる、という説明なら理解できますが。
うーん、なんか論点がずれてきているような…
> ドライバ開発で、割り込みハンドラでさわるリソースが、
> 通常コンテキストで触るリソースと競合するなら、
> 割り込み禁止以外ないと思ってたけど、そうでない
> 一般的なやり方があるなら教えてほしいのぉ。
ってのに対して「少なくともSolarisは違うよ」と言いたいだけなんだけど…
>>857 > たとえコンテクストスイッチしたとしても、その間に再度ハード割り込みが
> 次々に入ったらどうなりますか?それを避けるのが割禁の役目だと思います。
たとえば、ディスクIOに関する割り込み処理を行なっているときに
クロック割り込みが発生したら、クロックの処理を優先させるべきだからそっちの割り込み処理を先におこなう。
でも、クロック割り込みを処理しているときにディスク割り込みが発生しても、ディスク割り込みの処理は後回しにされる。
そういう制御を行なうために「割り込みレベル」ってのはある。
# これは「割り込みスレッドの優先度」とは違うもの。
でも、これはリソースの排他のためのものじゃないよね。
> そのwikipediaからの引用部分の前段には、割り込みハンドラが第1レベルと
> 第2レベルの2つの部分に別れているとあります。Solarisの場合であれば、
> カーネル(デバイス)内にあるのが第1レベルであり、その「実行中は割禁」される。
> また、デベロッパが作る割り込みハンドラが第2レベルであり、
> 一般的には「割り込みスレッド」と呼ばれている、と自分は解釈しています。
第2レベルもカーネル内にあるものだよ。
というか、Solarisでは第1レベルと第2レベルが明確に分かれておらず、
割り込みハンドラは、最初のうちは割り込んだスレッドのコンテキストを「借りて」処理をおこなう。
で、mutexでブロックすることになった時点で、完全なカーネルスレッドとして設定され、コンテキストスイッチが起こるの。
ただ、このとき優先度逆転現象が起こって競合したmutexがいつまで経っても開放されなかったらマズいので、優先度継承の仕組みが働くってこと。
調停スレッドを置く形態だとCASは別に必須じゃない。普通にwikipediaの記事が間違ってる。
なんだいきなり
>>825 スレッドプールとの何がちがうのかわからない・・・教えてエロイ人!
記事を斜め読みしただけだけど、 ブロックの中から外側のローカル変数を見れるようになってるっぽいのは便利そう どういう扱いなのかしらんけど
>>862 スレッドプール+タスクキューってのは定番の仕組み(たとえばJavaのThreadPoolExecutorとか)だけど、
それを利用しやすくするためにClosureを言語拡張として用意したのは凄い。
昔俺が作ったモニタだとハードウェア割り込みが入った
ら別の割り込みで失われる情報(割り込み要因とか)だ
け保存してまず enable interrupt してたな。
>>859 のいうようなレベル設定はハードウェアで実施さ
れてた。だから自動的に高いレベルのものが順次受け付
け可能だったよ。
>>857 は「じゃあ同じ要因の割り込みが割り込み処理中
に発生したら?」と思うかも知れないが、それはそもそも
処理が間に合ってないってことだ。
> ブロックの中から外側のローカル変数を見れるようになってるっぽいのは便利そう ていうかクロージャーってのは基本的にそういうもん。
867 :
801 :2009/09/09(水) 15:00:41
すまないですがデバイスドライバとかそういうのに限定した話ではないので 割り禁に相当するものはないという前提でおねがいします。 関係ないけど割り金って書くと玉がキュッとなるよね
>>862 スレッドプールを使いこなせている人にはあんまり関係ない気もするが、
初めてマルチスレッドに触れる人にとっては敷居が低いと思うの
>>867 >関係ないけど割り金って書くと玉がキュッとなるよね
女の子だからわからないわ
> 昔俺が作ったモニタだとハードウェア割り込みが入った
> ら別の割り込みで失われる情報(割り込み要因とか)だ
> け保存してまず enable interrupt してたな。
ふつーのOSは、割り込みを発生させた割り込みだけ禁止して
他の割り込みを許可して割り込みハンドラをよびだすよね。
だから当然他の割り込みは受付可能。ハンドラ呼び出す前に
発生させた割り込みまで許可するような変態^H^H面倒くさい
実装はゆるさん。
>
>>857 は「じゃあ同じ要因の割り込みが割り込み処理中
> に発生したら?」と思うかも知れないが、それはそもそも
> 処理が間に合ってないってことだ。
間に合ってないっつーか、割り込みコンテキストで割り込みを
発生させた要因をクリアもしくは禁止しないで、割り込み
コンテキスト抜けたら無限に割り込み入り続けるっつーことを
言ってるだけなんじゃね(レベル割り込みなら)
言語本ではなくマルチスレッドプログラミングの基本を概念からわかりやすくまとめた本があれば売れると思う
>>871 Win32マルチスレッドプログラミングがオススメ
コードはwindowsのapi使ってるけどスレッドの概念とか使い方とかわかりやすく書いてる
まぁ絶版になってるみたいだけどね
>>870 > ハンドラ呼び出す前に 発生させた割り込みまで許可
> するような変態^H^H面倒くさい実装
これ、割り込みコントローラがカスケード接続されてる
場合は要るかも。
玄関から割り込みを受け付けて「本当は誰だったか」を
調べて、そのハンドラを呼び出す前に他のハンドラの為
にもういっぺん玄関を開けたりとか。
結局「本当の誰か」に EOI 発行するまでその人からの
再度の割り込みは来ないからマクロに見れば同じだけど、
ハンドラ実行から後を別スレッドでやるように考えれば
割とスマートなんじゃないだろうか。
>>874 Java向けの本ではあるけど、確かにお薦めだと思う。
>>871 言語に依存しない入門書は確かに欲しい
各言語での扱いは巻末にちょろっと載ってるぐらいでイナフ
878 :
824 :2009/09/11(金) 22:29:34
>>859 遅レスになりましたが、頭を冷やして考えまてみました。
>でも、これはリソースの排他のためのものじゃないよね。
古典的なOSでは、割り込みコンテクストとサービススレッドとの間にある
リソースの排他のために、割り込み禁止、あるいは割り込みレベルを(一時的に)上げることで
実現していたけど、「少なくともSolarisは違うよ」ということですね....
>第2レベルもカーネル内にあるものだよ。
より正確には、カーネル空間内にある、ですよね。
>割り込みハンドラは、最初のうちは割り込んだスレッドのコンテキストを「借りて」処理をおこなう。
>で、mutexでブロックすることになった時点で、完全なカーネルスレッドとして設定され、
>コンテキストスイッチが起こるの。
つまり、通常は(競合が発生しない場合は)、割り込みコンテクストとしてハンドラは動き、
その間は割り込みレベルを上げる事で、(同じレベルでの)新たなハード割り込みの発生を防ぐ。
ただし、競合が発生すると(mutexでブロックされると)、割り込みコンテクストは終了して(リターンして)、
カーネルスレッドへのコンテクストスイッチが発生し、残りの処理を継続するという訳ですね。
これなら割り込みコンテクスト内での処理オーバヘッドを最小限に押さえつつ、
同時に、ハンドラとサービススレッド間のリソース排他を実現できるような気がします。
STRAMSのput&srvエントリと同じ考え方ですね。
詳しい解説、ありがとうございました。よい勉強をさせてもらうことができました。
自分としては納得できたので、このデバイスドライバ実装に関する話題は、これで終わりにします。
アトミック変数クラス(C++0xのstd::atomic<T>みたいなやつ)の ソースとか作り方ってどこかにあります?
>>879 もしWindows使いなら、Win32APIのInterlockedIncrementなど、Interlockedから始まるAPIの使い方を調べればよい。
「ソースとか作り方」って見た時、 一瞬、lock + cmpxchg とか lock + xadd のことかと思ってしまった。 そんなわけないよな。クラスって書いてるし。
883 :
879 :2009/09/12(土) 20:37:05
>>881 >>882 大体予想はつくし実の所もう作ってはあるんだけど、
キャッシュの整合性とか色々考え出すと生半可な知識ではどうしようもないので、
既存の検証された実装があればいいなと思って。
885 :
デフォルトの名無しさん :2009/09/13(日) 02:31:59
Art Of MultiProcessor本の10章 ABA問題Pragma10.6.1のところで CompareAndSet(T expectedReference, T newReference, int expectedStamp, int newStamp) ってなメソッドが定義されてる。 これってDCASっぽいのだが 質問は説明の後半 「C/C++でやるなら64bitアーキテクチャなら"stealing"bits from pointer, 32bitアーキテクチャでも間接参照?でできる(although a 32-bit architecture woild probably require a level of indirection.)」 ってあるがどうやるんだ? わかる人、教えて。
886 :
デフォルトの名無しさん :2009/09/13(日) 02:51:31
上の質問の追記 ReferenceとStampがどっちも小さい値なら 例えばintegerの上と下で16bitづつつかって maskで値を取り出すとか工夫できるだろうけど、 例えば32bitマシンで referenceもstampもどっちも32bitの値を使う場合にどうするんだろう ってのが質問。
そりゃペアで保持するオブジェクトの領域作って そこへの参照をCompareAndSetするんじゃないの?
888 :
デフォルトの名無しさん :2009/09/13(日) 11:05:39
>>887 cmpxchg使ったことある?
質問変えると
x86、Cでcmpxchgでどう書くか
890 :
デフォルトの名無しさん :2009/09/13(日) 11:34:02
俺わかんねorz 具体的にCとgasで疑似サンプルコード書いてもらえると助かる
みんな ほんとにできんの? 64ビットと32ビットのアーキテクチャのアプローチの違いもいわず ただ「オブジェクトつくって...」って 分かった気しただけで実装したことないんちゃうか cmpxchg使うんだよ
>>893 cmpxchg直接使うってバカか勉強中の学生以外
使わないと思うけど?
キミいくつなの?レベル低すぎなんだよね〜
x86前提ならそもそも64ビットCAS命令がネイティブでなかったっけ?
>>x86前提ならそもそも64ビットCAS命令がネイティブでなかったっけ? 元の質問読んだ? DCASっぽい動きをCAS命令でやるのってどうやるのって話。 誰も64ビット版ではstealing bits、 32ビット版ではindirectionの意味も語らず、 厨房よばわりしてるけど 誰も原著を読み込んでないし実装もできないじゃないか >>cmpxchg直接使うってバカか勉強中の学生以外 >>使わないと思うけど? >>キミいくつなの?レベル低すぎなんだよね〜 ようするに出来ないんだろ
897 :
デフォルトの名無しさん :2009/09/13(日) 17:19:40
>>894 このメソッド、
x86の32ビットと64ビットの両アーキテクチャ上で
Cで実装してみ?
cmpxchg使わないでw
public boolean compareAndSet(V expectedReference,
V newReference,
boolean expectedMark,
boolean newMark)
「現在の参照 == 予想される参照」であり、現在のマークが予想されるマークに等しい場合、参照およびマークの値を指定された更新値に原子的に設定します。
パラメータ:
expectedReference - 参照の予想される値
newReference - 参照の新しい値
expectedMark - マークの予想される値
newMark - マークの新しい値
戻り値:
成功した場合は true
898 :
デフォルトの名無しさん :2009/09/13(日) 17:20:42
IntelのTBBってどうですか 使える? これから主流になる?
一部はC++0xに取り込まれるので、やっておいて損はないと思う。
>>898 TBB使ったアルゴリズムが100%正しいのか
検証する手段がないから危険で使えないよ?
原子的に、って訳は正直どうかと思う
902 :
デフォルトの名無しさん :2009/09/13(日) 18:51:04
原子的に quark的に
不可分的に
905 :
デフォルトの名無しさん :2009/09/13(日) 21:07:54
結局、ここの連中は自分じゃコードが書けない 知ったかばっかりなんだな
907 :
デフォルトの名無しさん :2009/09/13(日) 21:31:47
>>906 馬鹿らしいが相手にしてやると
サンプルコードも書けない奴に先払いするやつなんていない。
slealing bitsってどういう意味だ?
せめてこれの意味くらいきっちり説明してみろ。
全然わかってねえじゃねえか、このスレの連中w
>>907 キミってその解ってないと卑下する連中と同列なんじゃないの?
ちなみに、煽れば回答でてくると思ってるでしょ?
>>907 キミってこんなのも書けないの?
template<typename T>
bool compareAndSet(T* const expPtr, T* const newPtr, const uint32_t expStamp, const uint32_t newStamp)
{
bool r = false;
if(v == expPtr && s == expStamp) {
TAS.lock();
if(v == expPtr && s == expStamp) {
v = newPtr;
s = newStamp;
r = true;
}
TAS.unlock();
}
return r;
}
TASぐらい実装できるよね?そこまでバカじゃないよね?
Javaの実装とVCかgccのcompareAndSwapのインラインアセンブラ
組み合わせれば実装ぐらいできるでしょ?それもできないってレベル低すぎるでしょ?
キミだめだわ
910 :
デフォルトの名無しさん :2009/09/13(日) 22:47:13
えーとだな、 そもそもの質問はArtOfMultiProcessor本の Lock-Free Queueの実装なんで おお威張りでlock()使われると 失笑するしかないんだがなw 君は本当の馬鹿なんだね
911 :
デフォルトの名無しさん :2009/09/13(日) 22:51:26
>>ちなみに、煽れば回答でてくると思ってるでしょ? 902に回答出てるじゃん。 できる人は出し惜しみしないで公開してるし回答もできるだろう。 ここに張りついてる連中は揚げ足とりばっかで 質問の本質も理解できない知ったかばっか
>>887 で終わってんのに何で続いてんの?
>誰も64ビット版ではstealing bits、
>32ビット版ではindirectionの意味も語らず、
当たり前すぎて説明する必要があるとも思わんわ。
64ビットではポインタのビットから一部拝借してスタンプに使う。
32ビットではポインタとスタンプをまとめて直接ではなく、
ペアの領域を作成してそのポインタで間接的にCASを行う。
>>912 uint64_t expV = ((((uint64_t)expPtr) << 32) | ((uint64_t)expStamp));
uint64_t newV = ((((uint64_t)newPtr) << 32) | ((uint64_t)newStamp));
return (expV == CAS64(&ptr, expV, newV));
これでOK?
914 :
デフォルトの名無しさん :2009/09/14(月) 00:17:59
>> 887で終わってんのに何で続いてんの?
909みたいなのが質問者を馬鹿にしたんで荒れたんじゃないの。
lock使ってCASを実装するような奴が威張り散らしてるのみて爆笑させてもらったよ。
いずれにしても知ったかが多いのが明らかになったのはよかったんじゃない。
>>912 当り前すぎたとしても、質問者みたいな初心者もいるから最初から説明してあげれば。
どう見ても、キミが質問者で 煽って回答を引き出してるだけに見えるけど。 週末だしね。
>>913 uint64_t expV = ((((uint64_t)&expPtr) << 32) | ((uint64_t)expStamp));
uint64_t newV = ((((uint64_t)&newPtr) << 32) | ((uint64_t)newStamp));
火元の人 やり方が理解できない質問者 俺に分からないならこのスレにも理解できる奴いないんじゃね、とか思っていて、 それが態度にも滲み出ている 煽る人 分かってるつもりだけど分かってないで煽り続ける こいつを見た火元は「やっぱり分かってる奴いないんじゃないか」と思いこむ 住人タイプA 一目で分かるがお前の態度が気に入らないしコード示すのマンドクセ つーかこの説明で分かれボユゲ 住人タイプB みんな何言ってんだかわかんね
エスパーA エスパーB 神 ↓
霊能者 死んだ人物の正体が人狼か人間かを知ることが出来る 村人と狂人の区別などは無理
住人タイプBです でもコミュニケーション能力では僕の勝ちみたいです
エターナルフォースブリザード 相手は死ぬ
住人タイプBですが何か?
住人タイプC 住人タイプAのいう「ボユゲ」が解らない
ペットA にゃー
獣人タイプA グボァ゙ァ゙ァ゙ァ゙ァ゙ァ゙!!
おまえら…
Interlocked系の処理って32bit限定で使っても、 32bit互換動作させた場合は問題なく動くよな?
??
住人タイプBなりに色々調べてるんだが、間違いがあったら指摘してほしい 32bitOSだろうが64bitOSだろうが、4byte以下の変数はアトミック変数で、それより大きな変数はアトミックでない C言語の場合、更新処理を行う場合、Interlocked系の関数を使用する WinBase.hをのぞいてみると、 32bit環境でのInterlockedIncrement64等は、InterlockedCompareExchange64によるスピン実装されている 32bit用のInterlockedAnd等は実装されていない? ターゲットIA64以外では、次のように定義されている #define InterlockedIncrementAcquire InterlockedIncrement #define InterlockedIncrementRelease InterlockedIncrement つまり、InterlockedIncrementはAcquireの機能もReleaseの機能も持つ? 何言ってんだかわからなくなってきた 32bitで論理演算をアトミックにやる方法はないのか? Interlocked系以外でメモリバリアっぽいことする方法がわからん さらにWinBaseを調べてたらInterlockedPopEntrySListなるものを発見 これがお前らがずっと言ってたLock-Free Queueってやつか!? もうちょっと調べてみるか
>>930 > 32bitOSだろうが64bitOSだろうが、4byte以下の変数はアトミック変数で、それより大きな変数はアトミックでない
一般に
バスに1サイクルでアクセスできるのであれば, 少なくともロード/ストアは保証される
o 32bitマシンで, バス幅が 32bit あって 4n 番地に 32bit 以下のオペランドをアクセス
o 64bitマシンで, バス幅が 64bit あって 8n 番地に 64bit 以下のオペランドをアクセス
など
CAS 系の命令を持っている場合, ロード/コンペア/ストアの間バスをロックする様に
設計されてる. (x86の場合は, lock prefix つけるんだっけ?)
通常, このタイプの命令も上に書いた制限が付く
RISC 系のマシンの場合, CACHEがあること前提で, CAS 系の命令を実装しないで
Load-Linke/Store-Conditional 系の命令を実装していることもあるので,
アトミック処理の一番プリミティブな部分は CPU によってすべて異なると
思っておいた方が良い
とりあえずここは必読。
http://msdn.microsoft.com/ja-jp/library/bb310595%28VS.85%29.aspx で、
_ReadBarrier コンパイラに対するread-aquire
_WriteBarrier コンパイラに対するwrite-release
_ReadWriteBarrier コンパイラに対する完全なバリア
MemoryBarrier CPUに対する完全なバリア
こうなってるように見える。
InterlockedIncrementAcquireとInterlockedIncrementの関係は、Windows用の
VC++のライブラリとしてなら同一視しても構わない、ということだと思われ。
Xbox用のライブラリとかなら別のコードを吐いたりするんじゃないか?
933 :
930 :2009/09/17(木) 11:33:43
レスサンクス! 基本的に自動でアライメントされると言う事で、あとはバス幅が64bitあれば問題ないのか! バス幅64bitなんて普及してたっけか Cでもメモリバリア普通にあるのな。何で見つからなかったんだ・・・ 移植性を考えたらちゃんとInterlockedIncrementAcquireとか使ったほうがよさそうですね
>>931 1バスサイクルは分割できないけどアトミックとは呼ばないんじゃないか?
CASなどでアトミックアクセスするところへ1バスサイクルだからといってもメモリ読み書きはするべきではなく、アトミック命令で読み書きするべきじゃないかな。
住人タイプBですがlinuxでvolatile sig_atomic_tな大域変数はmutexロックなしで読み書きしても問題ないですよね?
いいえまったく問題あります
> いいえまったく問題あります どのように?
> 釣だろ? 頼むから釣だと言ってくれ 釣りじゃないですよ
volatile sig_atomic_t は signal ハンドラと通常のルーチン間での 不可分なアクセスを保証するだけ。thread とは何の関係もない。
>943-944 理解できました ありがとうございます 滝に打たれて修行してきます
>>938 CASとかの話はチンプンカンプンな住民タイプBだけど、
その大域変数へのアクセスがどんな機械語に展開されるかは
コンパイラの実装しだいだと理解してる。
1語であれば安全かもしれないけどそれは保証されないし、
数語に展開されればその実行途中で他のスレッドへの
コンテクストスイッチが起きる可能性があることは予測できる。
だから、
>>938 の読み書きは問題ありだと思うよ。
947 :
946 :2009/09/18(金) 19:44:52
リロードしとくんだった....orz
>>947 リロードは戦闘に高揚をもたらすのでお勧め
>>938 シングルプロセッサシングルコアなら問題ないかもね
よく「シングルプロセッサなら」と言う人が居るけどさ 実際に変数を「読み書き」すると言っても 本当に「読む」と「書く」を完全に独立して行うことなど、あまり無いだろ。 つまり、数値変数を+したり、ポインタを進めたり あるいはリンクリストを手繰って更新する場合などにしろ 一度読んでから、その値を元に書き込むケースが多いわけ。 つまり、この読んだ直後にコンテキストスイッチが入って別のスレッドに割り込まれたら たとえシングルプロセッサであっても正常に動作しない。 (こうならないために、アトミック命令というのが存在するんだけど) その辺をわかってない奴が「シングルプロセッサでは再現性の低いバグ」を混入させておいて 「マルチプロセッサだとうまく動かない」と騒いでいることも多い。
ポカーン・・・?
おちつけ
yes, really excellent. good joke!
>>950 は三行目の日本語がおかしい(逆の意味に見える)けど、そこ以外は
read-modifiy-writeの一般的な危険性を普通に語ってるだけじゃね?
特におかしなことは言ってないように見えるが。長い割に大したことも言って
ねーけど。
956 :
950 :2009/09/20(日) 10:09:45
高度すぎてお前らには理解できなかったか・・・
高度でも何でもない基本だろw バスロックとかキャッシュ整合性とかを絡めてくるなら、まぁ若干高度な話かな、と 思わなくもないかもしれないが
>>950 「シングルプロセッサなら」、という人は、
まず前提として、普通、割り込み禁止にしてコンテキストスイッチが起こらないようにしてから、
共有変数の操作をしている。
だから、「シングルプロセッサなら」、というのは普通にありえる。
>>958 スレの流れを読み直したほうがいいと思うよ。
まず
>>938 の「mutexロックなしで読み書きしても」という質問に対して、
>>949 が「シングルプロセッサシングルコアなら」とレスし、
さらに
>>950 が「....と言う人が居るけどさ」とツッコミを入れてる。
だから、
>>958 の前提は(一般的には常識かもしれないけど、)
今のスレの流れでは的外れになってしまう。
どうでもよくね?
>>959 なるほど、sig_atomic_tは唯のintのtypedefだからな。
volatileはマルチスレッドで役立たずだし、lockしなくていいわけないよな。
そもそも何でそんな排他制御するのを嫌うんだろうなあ。 そんなにパフォーマンスクリティカルなプログラムを作ってる人ばかりなのかな? もしそうだとしてもロックを局所化する方向で考えるのが現実的ですよね。 それとも排他制御するとコーディングが面倒くさいからかな? でも、意味不明なバグに悩まされる方がもっと面倒くさいですよね。 何か他に理由があるのかな…
「とりあえずやっとけ」がイヤなんじゃない? 「これはおまじないだから」みたいな感じでさ 正しく理由を知ろうと思ことはいいことだと思うよ まあ俺はvolatile一本だけどね(笑)
volatile はシングルプロセッサ/シングルスレッドでも必要な時は必要。 すれ違いも甚だしい。
簡単なことを聞いてもいいでしょうか? あるファイルに対して読み書きするプログラムがあります。 このプログラムは多重起動を許しており、同時にいくつものexeを実行できます。 この場合はマルチスレッドとはいいませんよね? 単一のプログラム内にて複数のスレッドを組む場合がマルチスレッドという考えでよろしいでしょうか?
正しい
一つの資源を食い合いするなら同等の考慮が必要 その場合はマルチプロセスになるのかな
正しい
メモリとかキャッシュとかレジスターとかバスとかマルチコア/プロセッサーが絡むと どうなっているのかよくわからないからいつもmutex頼みです これらのHW関連とマルチスレッドについて詳しく知りたい場合のよい方法を教えてください
沢山ペーパーを読んで、沢山ソースコードを読んで、沢山テストコードを書く事。
mutexで済むならmutexで行きたいし、行けるとこは行く。 ただ、マルチスレッドで書かなきゃならない状況だと、パフォーマンスへの要求が 厳しいことも多いし、粒度の細かい設計が必要になったらmutexのコストはマジで でかくなる場合がある。 まぁ他にもABBA問題とか細かい話はあるけど、その辺は副次的な問題で、本当に スレッド間通信コストが重要になることもそれなりに多いんじゃねーかな。 それに、ある意味アトミックオペレーションは最小の排他なんだし、低水準から 固める派としては押さえておきたいだろう。
自分は低水準な(HW関連な)事柄は、ほとんど考えないな。 mutexのコスト(=オーバヘッド)を考えるよりは、 いかにmutexを減らすか、言い換えると、いかにスレッド間の 結合度(同期)の少ない並行/並列アルゴリズムを設計するかに関心がある。 UNIXだから移植性も大事で、それにはCPUアーキテクチャに依存した 設計は避けべきだから、できるだけ抽象的に考えるというのもある。 UNIXでもマルチスレッディングはそれほど特殊な技術ではなくなったしね。 ただ、それほどパフォーマンスクリティカルなプログラムは扱った経験が無いし、 正直言ってスレッディングには自信があるわけじゃないんで、参考程度かな。
>>972 > 低水準から固める派
安心して使える道具を揃えてゴリゴリ書くという意味で
は俺も昔はそうだった。だけど最近はトップダウンだ。
低水準からだとどうしてもパフォーマンスを上げきらな
い。結局大域的な設計で排他すべき要件を洗い出してそ
こだけ排他する。細々したコンテナ単位とかでは逆に排
他しない(業務要件としては複数コンテナを扱うことが
多いのでコンテナ単位とか普通ありえないけど)。
時代に逆行してるんだろか…。
ガチでぎりぎりの性能を引き出すことを求められる現場であればあるほど、低水準とか ハックとかが出てくるようになる、という傾向は今も変わらないよ。 ただ、そういう現場は激しく減った。 MTはやっぱりパフォーマンスの為に必要になることが多いから、他のスレよりは割合 が多いだろうけど。
976 :
973 :2009/09/20(日) 19:25:56
>>973 のパフォーマンスクリティカルな話を補足すると、
一応は性能要求/予測/設計/測定/改善といった開発プロセスはふむけど、
予測と改善(=チューニング)の段階で、mutexのオーバヘッドは定数として
計算することが許されるレベルのプログラムだということ。
言い換えると、定数だからmutexの発行回数(=係数)は考慮するけど、
mutexそのものを改善しなければならないほどのプログラムではない。
(少なくとも基幹業務処理のような単位時間あたりのトランザクション数や、
科学計算のような絶対的な性能を要求されるプログラムじゃない。)
基本的には、各段階ごとにきちんと記録を設計書として残すことが
大切という考え方。もちろん予測と結果が大きく外れることはままあるけど、
記録を元に外れた原因を追求し、それを次の開発に生かそうという発想。
システムが複雑だから、なかなか上手くいかず、理想論に近いんだけどね。
つーか、色々な用途に合わせたlock-free queueの安定した既製の実装が出回ってない、 ってことだけがlockを選ぶ理由になっていることも多い訳で。実装難度を考えないなら、 設計的には明らかにlock-free queueが一番適合するという事例は多い。ただ、自分で 組むほどじゃない、ということが多いだけで。 でも、自分で組むことでも何でもしなきゃならないこともありますよ、って人もいる のに対して「自分は設計だけで何とかなる事例しか手掛けてこなかったよ」と語ろう とする意図は分からないな。そういう事例が世の中に多いことくらいはほとんどみんな 分かってるんじゃないかと思うけど。 もちろん、単に趣味でlock-freeをやってみたいだけって人もいるだろうし、そういう 趣味の人を否定もしないけど。
lock-free なキューくらいなら 20 年位前に自前で作っ たことはあるよ。でも、そういったコンテナに付加情報 を色々付けようとしたら破綻しない? そういった単純な 仕組みで解決する問題の方が世の中珍しい気がするけど。
979 :
973 :2009/09/21(月) 00:51:43
>>977 うーん、何か気に触るような事を書いてしまったかな?
自分はlock-free queueの存在を否定なんかしていないよ。
lock-free queueについては全く知識がないから、それについては特に
触れなかった(触れられなかった)だけなんだけど。
逆に、パフォーマンスクリティカルな環境やハードウェアリソースが
ギチギチな環境であれば、lock-free queueを積極的に使うべきだろうし、
おそらく使わざるをえないケースも多いのだろうと思っている。
ただ、
>>970 の質問に関しては想定している環境は明記されていなかったから、
一般的なmutexで済む事例もあるし、もしも
>>970 がそういう環境であれば、
HWとの関連でアレコレ悩むよりも、いかに上手くmutexを使いこなせるかについて
設計技法に気を配るほうが前向きでは、と(長々としたレスで)助言しただけ。
(
>>976 のカキコは余計だったかもしれないが....。)
980 :
973 :2009/09/21(月) 01:11:24
(
>>979 の続き)
あと、
>>977 からは、lock-free queueを絶対的な物として
位置づけているように感じとってしまったのだけど、
>>977 自身が語っているように実装は難しいものなんでそ。
CPUアーキテクチャには詳しくないから、lock-free queueに関連した
命令コード(CAS命令?)とかについてはずっとROMっていたけど、
結局、スレッディングの基礎知識はある(と思っていた)自分にとって、
分かりやすいと思える解説や紹介リンクは見つけられなかった。
あげくのはてにIntelの仕様書嫁(
>>731 )と言われるしまつだし。
そんなlock-free queueを(おそらく初心者だと思える)
>>970 に勧める
というのは、いかがなものかと思う。また、このスレは相談室スレなんだから、
質問主が「そういう事例が世の中に多いことくらいは分かってるんじゃないか」
という思い込み(前提)でレスするのも不親切じゃないかと考える。
何レスまで行くと自動で落ちるんだっけ。そろそろ次スレの時期かな。
メモリの共用が起きなければ、lock freeは簡単だろ。 目盛り多く確保しておけばいい。
>>982 まったくそのとおりだ
メモリ共有がないのなら lock 操作すら不要なんだから
ただの queue を使えばいい
この話が何処に向かっているのか分からん
結局程度の差こそあれ誰も解っていないのではという気がしないでもない
www 俺以外全員馬鹿www wwwwwwwwwwwww
あくまで初心者への回答としての話であるべきところが一般論のように拡張されていた ことで、一般論としては言いすぎだろう、という意見が出て摩擦が起きたように見える
誤謬
lock-freeとか作れないけど、 ソレが有用な場面を挙げてみてほしいとか書いてみるテスト。
マルチスレッドのほぼすべてで有効だろ。
ASIOとか進捗表示とかのパフォーマンスの為じゃないお気楽MTなら不要かな それらはmutexすら要らない気もするが
>>990 「キュー内の要素数が 0 で無くなった時に読み出しス
レッドが待機状態であれば起こしたい」なんてよくある
要求だと思うけど、要素数とスレッド状態って atomic
に管理する必要あるよね?
そこに lock-free なキューを使うと何が嬉しいの?
lock-freeをある程度かじれば分かるが、要素数もatomicじゃなくていいよ スレッド状態は特権リング内の管理だろうから内部の挙動はシラネ ユーザーレベルで言うなら、lock-free queueをスピン&スリープで待機するなら スレッド状態も持つ必要なし
>>993 「要素数とスレッド状態の組」のことを言ってるんだけど? > atomic 性
要するにキューみたいな部品と、その外側の状態を紐づ
けて管理したいときに「lock-free なキューでござい」って
何が嬉しいの? ってさんざっぱら聞いてるんですけど。
>>994 スレッド状態要らないんだから組み合わせる必要も無いんじゃね?
細粒度MTではスピンウェイトの使い分けは常識だが、粗粒度MTの常識しか知らない奴が ずっと前から熱心に張り付いてね?
>990 989じゃないけど、じゃあ何故lock-freeなライブラリーは一般的に出回っていないの? 俺的にはlock-freeは都市伝説でないかと睨んでいる
要求によって全然組み方が変わるから
>>998 Javaは普通にlock-free queueあるぞ
1001 :
1001 :
Over 1000 Thread このスレッドは1000を超えました。 もう書けないので、新しいスレッドを立ててくださいです。。。