マルチスレッドプログラミング相談室 その7at TECH
マルチスレッドプログラミング相談室 その7 - 暇つぶし2ch352:デフォルトの名無しさん
08/12/20 01:51:56
>>351
ファイバーは移植のためにあるようなもので
新規プロジェクトで使う価値は無に等しい。

353:デフォルトの名無しさん
08/12/20 02:10:30
>>352
短絡杉
プリエンプティブであることは必ずしも望ましいことじゃない。
ゲームではファイバーが好まれる。
Larrabeeでもシェーダはファイバーで実装されるそうだ。
マルチコアでハイパフォーマンスだすためにファイーバーは重要。

354:デフォルトの名無しさん
08/12/20 02:31:59
自分でコンテキストスイッチとかめんどくせぇぇぇ

355:デフォルトの名無しさん
08/12/20 03:01:53
ちまちま排他処理すんのめんどくせぇぇぇ

356:デフォルトの名無しさん
08/12/20 12:21:50
>>352、353
マルチスレッドで複数の関数叩くのと、ファイバーを複数キックするのの違いってやっぱ、
同期処理が不必要(他のスレッドでキック中のファイバーは自動的に同期される?)だとか
スタックの制限(ファイバーキックされた段階でスタック指定できる)ですか?
いえ、無論色んな意味合いで違うことは判るけど。



357:デフォルトの名無しさん
08/12/20 16:20:24
int result = write( buf, size );
if( result == -1 && errno == EAGAIN ) SwitchNextCoroutine();
I/Oイベントドリブンなスケジューラをみたことある。↑みたいなの。
あとは同期が要らないってのが素晴らしい。


358:デフォルトの名無しさん
08/12/20 20:34:51
VisualStudio 2010にはC#のyieldを使ったファイバーもどきライブラリが付いてくるらしいね

URLリンク(channel9.msdn.com)

359:デフォルトの名無しさん
08/12/20 23:50:27
それは歪でいまいちだね~
まずコルーチンがあって
それにスケジューラを足してファイバー
イテレータ風に味付けしてジェネレータ(C#のyieldのことね)
という階層があるべき姿だと思うな。

360:デフォルトの名無しさん
09/01/10 00:18:47
64CPU環境でスレッドを256本生成したときに
struct data[2000];
なんてあって、dataの個々の要素を排他的にアクセスしたい場合
pthread_mutex以外に使えそうな手段ってありますか?

CASってどうやって使うのかよくわからんし助けて



361:デフォルトの名無しさん
09/01/10 00:48:43
pthread_mutexでマズい理由は?

362:デフォルトの名無しさん
09/01/10 00:58:20
>>361
2000個もpthread_mutex_tって用意して使えるのですかね?

363:デフォルトの名無しさん
09/01/10 01:08:25
発想が変?

364:デフォルトの名無しさん
09/01/10 01:47:06
mutexを2000個作って問題ないと思うよ。
自分だったら、struct data[200] 全体に対して1個のmutexにして、それ
でパフォーマンスの問題が出たらそのときに対処を考える。
reader-writerロックが使えれば使う。


365:デフォルトの名無しさん
09/01/10 01:47:49
訂正。
> 自分だったら、struct data[200] 全体に対して1個のmutexにして、それ
struct data[2000] ね。


366:デフォルトの名無しさん
09/01/10 18:28:23
>>362
pthread_mutex_t はただのデータだから、何個作っても
そのプロセスのメモリ以外の資源は使わない

367:デフォルトの名無しさん
09/01/11 00:54:05
連結リストをCAS使って実装するときのお手本ってありますか?


368:デフォルトの名無しさん
09/01/11 01:04:19
>>367
URLリンク(www.cs.rochester.edu)

369:デフォルトの名無しさん
09/01/11 01:14:01
双方向は無いのか........................

370:デフォルトの名無しさん
09/01/11 01:50:26
双方向でできると思ってんのかっ

371:デフォルトの名無しさん
09/01/19 00:40:02
rw_lockAPIが存在する環境で
同じrw_lock変数を以下のような構造で使うのって
問題ないでしょうか。

func()
{
rw_lock(read)
if 条件{
   rw_lock(write)
rw_unlock(write)
}
rw_unlock(read)
}

372:デフォルトの名無しさん
09/01/19 02:34:03
オレオレOSのオレオレrw_lock APIなら大丈夫だけど?

373:デフォルトの名無しさん
09/01/19 13:24:35
実装次第だが、普通に考えるとデッドロックするな

374:デフォルトの名無しさん
09/01/19 21:32:54
r_lock 確保してるんだから if の中の w_lock が取れないだろjk

375:デフォルトの名無しさん
09/01/20 06:28:27
なぜrでロックしないといけないのかわからんけど、条件に関わるのか?

376:デフォルトの名無しさん
09/01/20 11:21:30
>>375
このパターン自体は典型的なケースだろ
APIによっては、ReaderとWriterの他に「Writerに変更可能なReader」が用意されていることもある

377:デフォルトの名無しさん
09/01/27 16:00:09
WindowsでCreateThread中Cランタイムに含まれる関数を使うとリークを起こすとありますが、
普段からCreateThreadは使わずbeginthreadを使ったほうがいいんですか?
完全にCランタイム使わずってのも面倒だし、内部で使ってる関数があるかもしれない
そういうことまで考えてあえてCreateThreadを使うメリットはあるのでしょうか?

378:デフォルトの名無しさん
09/01/27 16:06:34
軽い

379:デフォルトの名無しさん
09/01/27 16:14:38
ない

380:デフォルトの名無しさん
09/01/27 17:56:15
_beginthreadexでおk

381:デフォルトの名無しさん
09/01/28 14:15:26
ないな

382:デフォルトの名無しさん
09/02/01 13:59:30
pthreadでmutexで
再起ロックする場合と
依存関係をハッキリさせてスレッドIDとFAST_MUTEXで判別

どっちが高速ですか?

383:デフォルトの名無しさん
09/02/01 15:33:29
後者。
以前計測したことがある。

ただし、依存関係の洗い出し作業がとても大変だった。
デッドロックに直結するから、とても気をつけないといけない。

要求性能がシビアだったから後者で仕事のためにやったけど、趣味ならば前者をお薦めする。
排他制御がボトルネックになるようなら、前者で実装すればいい。

俺の場合は、本当に特殊で制限が厳しかったから前者でやっただけ。

384:デフォルトの名無しさん
09/02/01 15:35:13
×排他制御がボトルネックになるようなら、前者で実装すればいい。
○排他制御がボトルネックになってから、後者で実装すればいい。

385:デフォルトの名無しさん
09/02/01 15:38:02
FAST_MUTEXって何?

386:383
09/02/01 16:18:24
色々ぐだぐだだな。
お家で寝たいよ。

387:デフォルトの名無しさん
09/02/01 23:25:11
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:デフォルトの名無しさん
09/02/01 23:54:31
加算をアトミックにしたいなら正しいんじゃない。

389:デフォルトの名無しさん
09/02/02 00:06:27
>>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:デフォルトの名無しさん
09/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); // これがなければ大丈夫 }



391:デフォルトの名無しさん
09/02/09 15:33:18
よりによってここに書くか。すれ違いだWin32スレ行け。
DLLの勉強一からやりなおせ。

最初から全コードのせときゃもっと早く回答ついたんだろうが、ウザイからオシエネ。


392:デフォルトの名無しさん
09/02/09 16:58:44
DLL内でnewしたのをEXE内で解放したらエラー出るんじゃない?
そもそもshared_ptrだって内部で参照カウント用にnewしてるからDLLじゃ使えない気がするなー。

393:392
09/02/09 17:02:58
スレッドは全然関係ないね。うん。

394:デフォルトの名無しさん
09/02/10 05:13:43
>>390
たぶんこれだけで死ねる。
 std::tr1::shared_ptr<A> a(new A);
 X(a)();

395:デフォルトの名無しさん
09/02/10 21:54:55
DLLか・・・COMについて調べたほうがいいんじゃないですかね
いろいろヒントあるよ

396:デフォルトの名無しさん
09/02/14 15:33:17
shared_ptr使ってるくせにdeleter知らないとか

397:デフォルトの名無しさん
09/02/19 23:31:28
>>288
Windows Xp home SP3 で自作のTCPサーバ運用してるけど、インバウンド接続の
同時接続数の制限が10ってことはないよ。
今モニタ見ても20人くらい繋がってる。
p2pがすごい数でつながってるだろうし

この件についてはいろいろなひとがよく確かめずにいろいろ書いてる。
自分でちょっとやってみればすぐわかる。


398:デフォルトの名無しさん
09/02/19 23:33:34
>>397
実装はともかくライセンスで制限されてるはず

399:デフォルトの名無しさん
09/02/19 23:37:37
そうなんだよね。 使わないでくれという約束で みんな破って使ってるわけだ。

400:デフォルトの名無しさん
09/02/19 23:46:20
SQLだったかで試してたときにイベントログに制限されたメッセージが
出たことある。あとShare動かしてる時とか頻繁に出る気がする。
単純にセッションの制限では無かった筈。


401:デフォルトの名無しさん
09/02/20 00:12:50
MS製のサーバは独自に制限した実装  IISじゃなくてPWSだっけ
WMEとかはレジストリいじって50人くらいつないだりしてたな。

402:デフォルトの名無しさん
09/02/20 02:13:42
それとは別に、セキュリティ的な話で、
SYN_SENTなソケットをシステム全体で
10くらいしか持てないって制限もあったはず。

403:デフォルトの名無しさん
09/02/22 19:23:55
初心者な質問ですが、
Thread A        Thread B
for(;;)           for(;;)
printf("AAA\n");    printf("BBB\n");
という処理を行うと、AAA行とBBB行が入り乱れて表示されるんですが、
AABABB\n\n などと表示されることはありえないんでしょうか。

環境はWindows XPで、VC++2008EEでプログラムを書いてます。

404:デフォルトの名無しさん
09/02/22 19:36:03
>>403
ここらへんに何か書いてあるんじゃねーの?
URLリンク(msdn.microsoft.com)

405:デフォルトの名無しさん
09/02/23 04:04:56
>>403
バッファリング

406:デフォルトの名無しさん
09/02/23 21:19:24
スレッドに別のスレッドから信号を送って途中で処理をキャンセルしたいのですが、
現状、以下のようにしています。

void run() { // スレッド実行部
 for () { // 長いループ
  ...処理...
  if (check()) return; // 処理をキャンセル
 }
}

check()でキャンセルのフラグをチェックし、このフラグを別のスレッドから書き換えるという方法です。
でもこの方法だとループ内の処理が重くなったときにキャンセル操作に対する反応も遅くなってしまうため
どうしたものかと悩んでます。
スレッド内でタイマーのようなものを発行して、定期的にcancel()のチェックをするといった方法はできないでしょうか?
環境はVC9です。

407:デフォルトの名無しさん
09/02/23 22:47:56
>>406
別スレッドから強制停止するとリソースリークの元だよ。
  if (check()) return; // 処理をキャンセル
を重い処理の途中に幾つか入れる方がまし。

408:406
09/02/23 23:51:22
>>407
> を重い処理の途中に幾つか入れる方がまし。

どうも。やっぱりこういう単純な方法しかないですか。
重い処理を別スレッドで行わせながら
キャンセル操作の反応がよい安全な方法ってのはないんでしょうか。
cancel()を挿入しまくるというのもなんだかスマートじゃないなぁ・・・。

409:デフォルトの名無しさん
09/02/24 00:50:35
非同期に飛ばされるぐらいならコードが汚くなる方が良い


と思うのは俺だけじゃないよな?

410:デフォルトの名無しさん
09/02/24 01:12:42
その重い処理ってのがなんなのか
スマートとか言うならその重い処理をスマートに分割すりゃいいじゃない

どうしてもチェックしまくりたくないっていうなら処理を持ってるクラスのインスタンスを急にnullにしてやって
例外捕らえて終了してしまえ、最悪だけど

411:デフォルトの名無しさん
09/02/24 01:40:59
別プロセスにして殺すってのは?

結局そういうのって要求されるキャンセル応答時間次第。
人間相手ならmsecオーダでおkでしょ。
きっとループ1回につき1msecもかからないのでは?

412:デフォルトの名無しさん
09/02/24 01:51:03
ワーカースレッド2つ以上用意にして
対処すればよくね?

複数個のスレッドでビジー状態になるなら
その処理内容そのものを分割しタスク化した方がいい


413:デフォルトの名無しさん
09/02/24 02:50:07
違う質問スレで質問した後でこちらを見つけたので一応こちらでも・・・

CreateThread関数で第三引数をクラスのメンバ関数にしたい場合は
どういう記述をすればいいのか教えてください
よろしくお願いします



414:468
09/02/24 02:56:15
>>410
>その重い処理ってのがなんなのか

例えば大きなサイズの行列計算や、待ち行列を使った探索問題なんかを想定しています。
問題を分割することはある程度はできるんですが、それはそれで頑張るとして、
それ以外のアプローチははないかなと。

>>411
> 別プロセスにして殺すってのは?

すみません。よくわかりません。
別プロセスならば殺しても元のプロセスに影響がでないという意味でしょうか。
>>410の後半で言ってることに近い

>>412
> ワーカースレッド2つ以上用意にして 対処すればよくね?

同じスレッドオブジェクトをAとBの2つ用意して、
Aが動いてるときにキャンセルしたときはキャンセルしたふりをして
(Aの計算は次のcancel()チェックまで続いてる)、
新規の呼び出しがあったときはBを動かすというイメージですか?これはいけるかも…。



415:468
09/02/24 02:58:01
一部修正

>>410の後半で言ってることに近い
 ↓
>>410の後半で言ってることに近いですか?



416:デフォルトの名無しさん
09/02/24 07:10:44
>>413
コールバック関数にはstaticなメンバ関数(クラスメソッド)しか使えない。
コールバック関数を使うAPIは大抵ポインタ型の引数を渡せるから、
クラスを使いたいときはそこにthisポインタを渡して使う。

417:デフォルトの名無しさん
09/02/24 08:52:04
>>413
できない
普通の関数作ってその中で呼び出す

418:デフォルトの名無しさん
09/02/24 16:53:09
>>416‐417
ありがとうございます
とりあえず、>>417の方法でやってみます

419:デフォルトの名無しさん
09/02/24 20:52:23
>>414
別プロセスにすると、ターミネートしたときのリソースの開放をOSがやってくれる
ってことではあるまいか。
それはともかく、その長い処理がうまく分割できず、どうしても時間がかかる場合は
汎的には、キャンセルボタンの入力を取得する側(フラグを立てる側ね)で、キャンセルが
押されたからしばらく待てっていうサインをユーザーに与える方が重要な希ガス。

420:デフォルトの名無しさん
09/02/24 21:45:33
別プロセスのほうがクリーンアップの点では簡単&安心だなあ

ただ、多くの情報を受け渡したり、途中で通信が必要だったりすると
しんどいけどな

421:デフォルトの名無しさん
09/02/24 23:05:03
しんどいと言うか、性能の問題がでるかも

422:406
09/02/25 00:45:53
>>419-
なるほど。別プロセスにすることも検討できそうです。
なんとなく雰囲気は分かりました。どうもありがとう。

423:デフォルトの名無しさん
09/02/25 18:38:04
処理毎に別プロセスって、昔の業務アプリみたいだな。っていうか、
今でもVBあたりでそんな開発やってそう。

1画面=1exeファイルで、画面間はsystem()でプロセス呼び出し。
画面フォーム上で入力したデータ等は、ファイルに書き出して渡す。

大抵、exeファイルの名前は全部数字と意味不明なアルファベットで、
メモリ食いまくりで、やたらに遅い。(w

424:デフォルトの名無しさん
09/02/25 19:28:47
大規模なアプリはマルチプロセスの方が開発しやすいね
Windowsの場合は性能的にマルチタスクに向かないけど

425:デフォルトの名無しさん
09/02/25 21:04:19
>>423
unixだとマルチプロセスは多いけどな。

VB6のアプリだとそういう作りになるのは仕方ない。
モジュール分割の手段がCOMしかない。
20画面もあるとロードモジュールが10M超える。
IDEに読み込んだりコンパイルするのにも一苦労。
プロセス間でDBのセッションを引き継げたらマルチプロセスでも軽くなるはずなのだけど、
それも出来ないからDBの接続でどうしても画面遷移が重くなってしまう。

426:425
09/02/26 01:19:09
>>424
マルチスレッドは、スレッド間のメモリ保護機構がないので、他スレッド
による破壊のリスクと引き換えに、高速なデータ共有が可能と思うが?
Windowsがマルチタスクに向かないとか、何を根拠に?

>>425
昔はメインメモリが少なく高価だったという事情もあるし、「unixだと」
という括りはどうかな?

20画面なんて、そんなに大きな規模なプログラムじゃないよね?その程度
の規模で単純にVBのソースだけなら、10MBを超えるようなことはないの
では?

確かにVB6当時のハード環境(Pentium 300MHz~1GHz, メモリ64MB程度?)
でのビルドは遅かったかもしれないが、VBはVCよりは速かった様に記憶
しているけど?

それと、プロセス間でDBのセッションを引き継げないのは、VBや、Windows
に限定された話ではないのでは?

極端に処理が遅い業務アプリは、データベースの設計自体に問題があり、
無駄にDB間でレコードをコピーしたり、テーブルのリンクが必要だったり
ということが多い気がする。

427:デフォルトの名無しさん
09/02/26 01:55:03
プロセス間のデータ共有なら共有メモリがあるよ
特に親子関係があれば、mmap ANON とかでお手軽極楽

スレッドのメリットは(スレッド間なら)高速にディスパッチ出来る点だね
heap だろうとなんだろうとメモリは全部共有されるというのは
メリットでもあるけど、デメリットでもあるかな。
バグの原因になりがちだよね


428:デフォルトの名無しさん
09/02/26 03:45:35
構造化されたデータを別プロセスと共有メモリ経由でやりとりするとして

c構造体ならまあなんとかなるんだが(いやそれでも大変だが)
c++クラスだとすんごいやりにくい

何かウマい方法あります?

受け渡し用にクラス作るのもアホらしいし・・・
変態的テンプレートでなんとかなるもんだろうか

それとも単なる通信バッファとしてしか使わない?

429:デフォルトの名無しさん
09/02/26 03:52:42
C++ならCの構造体も使えるんじゃ…。

430:デフォルトの名無しさん
09/02/26 04:07:16
そういうのはソケット使って単純化してる。
プロセス間共有メモリは後で環境や仕様が変わったときに
変更が大変だし流用も難しい。バグも入りやすい。
パフォーマンスを上げたいとか、よっぽどの理由でも
ない限り使われないんじゃないかな。
スレッドと違って>>428の言うデメリットもあるし。
ウマい方法はありません。

431:デフォルトの名無しさん
09/02/26 04:53:41
>>426
酷いミスリードだな。>424はマルチプロセスによるマルチタスクという技法がWindows向けでないと言っているように見えるが。

432:デフォルトの名無しさん
09/02/26 04:59:25
IE8はマルチプロセスですぜ

433:デフォルトの名無しさん
09/02/26 05:49:22
>>426
お前は誰なんだ

434:デフォルトの名無しさん
09/02/26 06:45:39
unixといえば今でもパイプをfork/execで分け合ってというイメージが強いな。
DBのコネクションは知らないがファイルハンドルならプロセス間で受け渡せる。
Windowsにもハンドルを複製して子プロセスに渡すオプションはあるのだが、
OS/2やNTは最初からスレッドをサポートしてたのであまり使われない。

435:426
09/02/26 17:42:01
>>425
ハンドルの複製に失敗しますた。orz 426=423です。

>>431
未だにWindowsがunixに劣っていると思っている原理主義者か、TRON房かも。
何を以ってunixを定義しているのか聞いてみたい。

>>434
ハンドルをコピーしたりは、MS-DOSにもあったかな。INT 28Hだか忘れたけど、
プリンタスプーラ用の割込使えば、一応擬似マルチタスクで一部のシステム
コールを呼べた。

デュアルコアやクァッドコアのCPUだと、マルチスレッド化すると理論上
2倍や4倍で動くと勘違いしているヤツもたまにいるよね。おまえのOSは
いったいいくつプロセスが動いていると思っているんだと、小一時間。(略

436:デフォルトの名無しさん
09/02/26 18:11:07
WindowsがUNIXより優れてると思い込んでるなら
まずはその幻想をぶち壊す!

437:デフォルトの名無しさん
09/02/26 18:40:58
>>436
上条さん乙。
つか、んな事誰も言ってないから。

438:デフォルトの名無しさん
09/02/26 23:22:19
マルチスレッドスレでマルチプロセス云々言ってる時に何の前提もなく
「マルチタスク」なんて言う奴は普通にスルーでいいと思うんだけど...

439:デフォルトの名無しさん
09/02/26 23:47:59
よ~し、おじさんもマルチプログラミングとかタイムシェアリングとかの古語を持ち出しちゃうぞ。

440:デフォルトの名無しさん
09/02/26 23:51:02
>>435
実質、4coreXeonのシステムだとOpenMPで4スレッドにして3.9倍速くなるけどね。
逆に、>435のCPUはOSをアイドル状態で動かすだけでどんだけ負荷喰ってるんだって話だな。

441:426
09/02/27 10:22:04
>>440
スレッドでどんなコードを走らせているか知らないけど、スレッド内で
アクセスするデータもコードも、CPU内のキャッシュに収まるくらい
小さなプログラムでもない限り、そういう結果はまずありえないと思うな。

それとも脳内キャッシュ?

442:426
09/02/27 10:43:15
非同期I/Oを使わずスレッド内でファイルI/O待ちしているとか、ネット
ワーク物理層の帯域幅に比べて通信速度が遅く、スレッド化でマルチ
セッション化できるといった、ある意味冗長な造りのプログラムなら
ありえるね。

OSのアイドル状態を持ち出すあたり、他に何個のプロセスがいつ走って
いるか考えていないのかな?(w

443:デフォルトの名無しさん
09/02/27 10:43:58
>>441
OpenMP知らないなら黙っていた方がいいと思うよ。

444:デフォルトの名無しさん
09/02/27 10:45:51
>>443
3.9倍早くなるって
作ったプログラム全体?それとも特定の処理に
限定された内容?どっちなの?

445:443
09/02/27 11:04:31
>>444
私に聞くなw
恐らく演算に集中している部分じゃないの?
MKLなんかは大き目のデータのFFTでそれくらいのリニアリティを叩き出すから。

446:デフォルトの名無しさん
09/02/27 13:15:48
embarrassingly parallel なワークロードならそれくらい行ってもおかしくない

でも大抵の処理は並列化不可能な部分が無視できない量存在してて、
アムダールの法則でもって高速化の限界が簡単に見えてしまうと思うよ

447:デフォルトの名無しさん
09/02/27 13:58:29
>>436
コンシューマー相手のソフトウェアのパッケージ販売の観点からは
明らかに優れている。全然スレ違いだが。

448:デフォルトの名無しさん
09/02/27 19:47:19
>>443
OpenMP に期待しすぎ。

何でもかんでも 3.9倍になる魔法なら俺も欲しいが。(w

449:デフォルトの名無しさん
09/02/28 02:39:25
>デュアルコアやクァッドコアのCPUだと、マルチスレッド化すると理論上
>2倍や4倍で動くと勘違いしているヤツもたまにいるよね。おまえのOSは
>いったいいくつプロセスが動いていると思っているんだと、小一時間。(略

略とか言われても。誰か解読してあげてよ。
少なくとも実測で3.9倍でてるわけだから、理論上は4倍出ると言っても問題ないよな。
たくさんのプロセスが動いてるとき、マルチコアだとちゃんと速くなるよな。
意味不明。

450:デフォルトの名無しさん
09/02/28 03:13:14
どういう問題を解いて3.9倍なのか書かないと意味がないかと。

知人の計算屋さんがAMDの8CPU機にメモリしこたま積んで
巨大グラフを相手にした問題を解いていたことがありましたが、
問題の構造上メモリアクセスに局所性が全くないのでCPUの
速度や数以前にメモリ帯域が飽和して速度が頭打ちになると
ぼやいていた事が。

451:デフォルトの名無しさん
09/02/28 14:17:04
>>450
まあその辺に桁違いのコストを掛けてクリアしてることが
スパコンの存在意義だしね


452:443
09/02/28 16:53:30
>>448
期待するも何も、実験した結果だし。

>>450
>445に書いた通り、只管FFTを計算するようなプログラムと言うくらい。

その結果では、4core2cpuのシステムで、4並列まではびっくりするほどリニアリティがあるけど、
その先は一つ増やしても0.7個分くらいしかパフォーマンスが上がらなかった記憶が。
# 8並列で7倍くらいかな? 必要なら記録を探してくるけど。

尤も、自作のプログラムだと4並列でも8並列でも殆ど変わらなくて泣けた罠。
インテル某氏の話だと、MKLはOpenMPで並列化してもリニアリティを確保できるように
作られているそうで、折角FFTを使わない版を作ったのにお蔵入りになりそうだったり。

453:デフォルトの名無しさん
09/02/28 16:55:08
スパコンと言えばTOP500で10位にWin鯖クラスタが付けてたけど
(CPUとメモリだけ)似たような構成の他のと比べて特に劣ってるようでも秀でてるようでもなかった

454:デフォルトの名無しさん
09/02/28 18:46:09
>>452
OpenMP に頼って満足してる人はこのスレに用はないでしょ。
どうぞお引取りください。

455:デフォルトの名無しさん
09/02/28 19:01:43
>>454
>452じゃないけどここはマルチスレッド全般でしょ?
>1にも「OS・言語・環境は問わない」って書いてるんだからいいと思うけど
ただし>452=443=440はおバカさんだと思うけどねw

456:デフォルトの名無しさん
09/02/28 21:22:08
OpenMP の話題がまずいと言ってるわけじゃなくて、「OpenMP
に頼って満足してる人」って書いてあるんだが...。

スレタイに「相談室」って書いてあるのが見えませんか?

457:デフォルトの名無しさん
09/02/28 21:41:20
>>456
相談した人にOpenMPに頼って満足してるってレスするのは問題ないだろ

458:デフォルトの名無しさん
09/02/28 22:04:33
で、どこに相談した人がいるんだ? (w

459:デフォルトの名無しさん
09/02/28 22:09:48
俺は>452個人の話はしてないんだが。お前誰と闘ってるんだ?

460:452
09/02/28 22:13:07
まぁ、私は「OpenMPに頼って満足してる」のではなく、「OpenMPを巧く使うMKLに勝てなくて泣いてる」のだけれどねw

461:デフォルトの名無しさん
09/02/28 22:13:48
よくわからないけど、置いときますね。
#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)


462:デフォルトの名無しさん
09/02/28 22:35:01
>>450
おれは、>>452 個人の話をしてるんですけど。

まさか、>>454 に書いてあるアンカーすら見えなくなるほど
頭に血が上ってるとか? (w

463:デフォルトの名無しさん
09/02/28 22:48:56
>>462
俺は「OpenMPに頼って満足してる」のを理由に追い出そうとしたことに
ついて話をしている。>>452個人のことはどうでもいい。
どうやらただの煽りあいになりそうだからこの話題は終了する。

464:デフォルトの名無しさん
09/03/01 02:32:16
>>460
何故勝てなくて泣く必要があるのか少し気になる。

465:デフォルトの名無しさん
09/03/01 16:47:46
>>463
「相談した人もいないのに勝手に OpenMP に頼って満足してる人」は
このスレに用はないでしょ。

これでいいか?

> >>452個人のことはどうでもいい。

# >>452 にレスしてるのに、勝手に割り込んできて逆切れかよ...

466:デフォルトの名無しさん
09/03/01 18:49:02
OpenMPってどんなの?たとえば、Videoのエンコード・デコード
処理が書いてある逐次処理のCなりC++のソースコードが
あったら、ほとんど変更なしに並列化できるん?

それとも、既存のソースは一から書き直しくらいしないと
パフォーマンスは出ない?

467:デフォルトの名無しさん
09/03/01 18:53:11
相談者が現れたので>>452の出番ですwww

468:デフォルトの名無しさん
09/03/01 18:55:20
それ以前に446にふさわしい言葉は「ググれカス」だろう。

469:デフォルトの名無しさん
09/03/01 19:14:45
>>466
OpenMPスレという物もあってだな(ry

470:デフォルトの名無しさん
09/03/02 02:02:51
OpenMP詳細しらんが、既存のソースは1から書き直しまで
いかなくても、大幅に書き直さないとパフォーマンスは
でないのだろうな。常識的に考えて。

コア数に応じてリニアにパフォーマンスがあがって、既存
のソースから簡単に移行できますよ、っつーなら神なのだが。

471:デフォルトの名無しさん
09/03/02 02:35:03
それを可能にするには関数型など副作用のない言語が有利
今更言うことでもないが

472:デフォルトの名無しさん
09/03/02 02:38:08
>>471
んなこたーわかってんだよ。新規にはじめる分野はそれでもえーよ。
資産の移行も重要なんだよ。

473:デフォルトの名無しさん
09/03/02 02:42:00
おまえの書いたコードなんぞ資産と呼ぶ価値も移行する価値も無いから気にすんな

474:デフォルトの名無しさん
09/03/02 02:46:42
>>473
俺の書いたコードが資産だなんて、いついったんだよ?
煽るにしろ、頭の悪さが透けてるんだよ。

475:デフォルトの名無しさん
09/03/02 03:08:36
>>472の「おまえ」が>>474だなんて、いついったんだよ?
煽るにしろ、頭の悪さが透けてるんだよ。

476:デフォルトの名無しさん
09/03/02 11:59:03
これは惨めなミス。

477:デフォルトの名無しさん
09/03/02 13:39:15
>デュアルコアやクァッドコアのCPUだと、マルチスレッド化すると理論上
>2倍や4倍で動くと勘違いしているヤツもたまにいるよね。おまえのOSは
>いったいいくつプロセスが動いていると思っているんだと、小一時間。(略

478:デフォルトの名無しさん
09/03/02 23:44:21
>>477
こいつの言ってることまじでわからんのだが・・・。
こいつがアフォなのか、俺がアフォなのか誰か解説よろしく!

479:デフォルトの名無しさん
09/03/03 00:03:02
コア1 ●◎◎◎◎◎◎◎◎◎
コア2 ●○○○○○○○○○
コア3 ●○○○○○○○○○
コア4 ●○○○○○○○○○

         ↓

コア1 ●◎◎◎◎◎◎◎◎◎
コア2 ●◎◎◎◎◎◎◎◎◎
コア3 ●◎◎◎◎◎◎◎◎◎
コア4 ●◎◎◎◎◎◎◎◎◎

○ 空き
● 別プロセス
◎ 自プロセス

4倍になる

480:デフォルトの名無しさん
09/03/03 00:28:55
>>477
基本的には>>477がちょっとずれていると思う。
コア数に比例してリニアに2倍4倍にならないのは事実。
でもハウスキーピングなプロセスの数云々は性能を押し下げる
理由としてはどちらかというとマイナーな部類だと思う。

481:デフォルトの名無しさん
09/03/03 00:29:19
ちょっとゲロでちゃった

482:デフォルトの名無しさん
09/03/03 00:35:18
並列化効率の話がまず最初だよね。
アムダールの法則。

483:デフォルトの名無しさん
09/03/03 00:38:03
>>480
いや、こうまで単純化していいかどうかわからんが、
ハウスキーピングのプロセスがほぼsleep状態と
仮定したら無視できるわけで。

というより、4コア100%使用する処理走らせるんだったら、
無視できるほどなわけで(スワップデーモンとか
ハードアクセスの重いスレッドが走らない前提なら)。

バスネックでリニアに伸びないとか、キャッシュの競合
だとかいうならまだしも。やっぱり俺には>>477はさっぱ
りわからん。

484:デフォルトの名無しさん
09/03/03 01:50:33
アイドル状態のプロセスでもビジーループでCPU消費してる
とか思ってんじゃないの

485:デフォルトの名無しさん
09/03/03 01:56:06
>>484
単に1つのプロセスが1コアを占有し続けると考えているのではあるまいか。

486:デフォルトの名無しさん
09/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 内に
記述した途端にフリーズする様になってしまいました。
コメントアウトすれば、問題なく動作します。

ファイルをアップロードしたので、見ていただけないでしょうか?
URLリンク(www3.uploda.org)
受信パスは test です。
どのように修正すれば良いか、ご教授願います。
よろしくお願いします。

487:デフォルトの名無しさん
09/03/14 05:54:15
>>486
windowsのウィンドは、プライマリスレッドで生成しないと
いろいろいろいろいろいろいろいろトラブルが起こるので、そういう設計は見直した方がいい。
そもそも子ウィンドウは親ウィンドウと同じスレッドで生成しないとトラブルになる。

例えば親をAスレッドが、子をBスレッドが作ったりすると、
親のプロシージャはAスレッドが実行し、子のプロシージャはBスレッドが実行することになる。
子から親への通知や親から子への通知がメッセージで発生したら発生したら、
デッドロックの宝庫になることは想像に難くない。

それ以前にメッセージループって親子で共通のような気が・・・

488:デフォルトの名無しさん
09/03/14 06:05:38
>>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++;


489:デフォルトの名無しさん
09/03/14 06:16:38
WM_CREATEで無限ループしたらCreateWindowから制御が戻らないわけだが

490:486
09/03/14 15:00:34
>>487
色々と問題があるという事ですか...
そこまでは考えておりませんでした。
ですが、今はこの枠組みで作ろうと思います。
アドバイスありがとうございます。

>>488
メッセージのループを回すのを忘れておりました。
ありがとうございます。
ただ、今回はメッセージのループのみが欲しいので
ウィンドウは非常時で構いません。

>>489
確かにそうでした。
あるメッセージを受けた時に
その中で Sleep(1000); を実行する事にしました。

・・・が、それでも親ウィンドウが 1000 ミリ秒 固まってしまいました。

以下の様にしておりますが、
これでは各ウィンドウは別スレッドで動かないのでしょうか?
URLリンク(www2.uploda.org)
受信パスは test です。
よろしくお願いします。

491:デフォルトの名無しさん
09/03/14 15:07:12
作ろうと思います、じゃねー
動作が未定義なんだからそんなプログラミングすんな

492:デフォルトの名無しさん
09/03/14 15:18:07
>>491
互いのウィンドウでメッセージのやり取りを頻繁にするような事は致しません。
親スレッドとは独立したウィンドウプロシージャのメッセージループ
(表現が合っているかは自信がありませんが)が欲しいのです。

以下、長文失礼します。

5 [msec] の情報が入るサイズのバッファを複数用意し
信号をバッファに入力し、あるバッファが満タンになったら
windows からメッセージが投げられ、
受け取ったメッセージ内で信号処理をする、
というものを作っています。
この時、信号処理に時間がかかるため
常にメッセージを受け取った時の処理を行ってしまい
メニュー操作が出来なくなる状態です。

アプリケーションを強制終了すると、信号処理した数値列が
ちゃんとファイル出力されているので
信号の入力及び信号処理は問題なく進んでいます。

これを解決するにはメニューを持つウィンドウと
メッセージループのあるウィンドウを別スレッドで走らせれば良い
と考えました。


493:492
09/03/14 15:53:32
連稿失礼します。
Sleep(1000); を

int i, j;
for (i=0, j=0; i<1000000000; i++)
j++;

としてみましたが、結果は同じでした。
親ウィンドウのスレッドにフォーカスが戻っていないのでしょうか?

494:デフォルトの名無しさん
09/03/14 16:43:47
子ウィンドウ作る必要なんて無いところを、
わざわざ回りくどいやり方しているようにしか思えないんだけど。
ワーカースレッドにデータ送りたいだけじゃないの?

495:デフォルトの名無しさん
09/03/14 18:10:18
>>494
ワーカースレッドについて知識が無かったのでググってみました。
MFCでのみ使用可能な関数でしか作れない事が判りました。
今はSDKで組んでおり、MFCは使った事が無いので今の私には使えそうにありません。
情報ありがとうございました。

496:デフォルトの名無しさん
09/03/14 18:28:36
>>495
ワーカースレッドは概念であって、SDKのみだから作れないということは無いよ

そもそも、貴方のやろうとしていること自体がワーカースレッドの利用だ

497:デフォルトの名無しさん
09/03/15 15:23:44
>>496
ワーカースレッドについて調べ方が間違っていたようです。
もっと調べを進めます。ありがとうございます。

498:デフォルトの名無しさん
09/03/15 20:09:14
>>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へ戻る

499:デフォルトの名無しさん
09/03/15 20:18:36
>>498
あー便所で説明してくれないと解らない

500:デフォルトの名無しさん
09/03/15 20:42:55
>>499
ウホッいい男!

501:492
09/03/15 20:45:19
>>498
詳しい構成、本当にありがとうございます。
頑張って理解してみます。

502:デフォルトの名無しさん
09/03/27 03:19:19
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();
}


503:デフォルトの名無しさん
09/03/28 18:55:17
>>502
どうするかは、何のクラスかによるだろう。
一般論でAが、sync_fun()実行中に破棄される可能性があって、
どうしても回避できないならAのデストラクタでunlockする。

504:デフォルトの名無しさん
09/04/04 16:12:48
ダウンローダをマルチスレッドで作成しようと思っているのですが
スレッドを10個作り
それぞれにURLを追加して、次々にダウンロードさせる仕様にしようかと思っていますが
このスレッドの終了タイミングはどういった条件で終了すればいいでしょうか?

メインスレッドが終了するとこの10個のスレッドも終了するので
どうしたものかと考えています

505:デフォルトの名無しさん
09/04/04 16:19:45
あげます
すいません

506:デフォルトの名無しさん
09/04/04 16:20:37
.

507:デフォルトの名無しさん
09/04/04 16:36:26
>>504
何を聞きたいのかよく分からんけど、
メインスレッドで10個のスレッドの
終了待ちさせれば良いんでないの。

508:デフォルトの名無しさん
09/04/04 16:45:56
>>507
なるほど
そういう手がありましたか
ありがとうございました

509:デフォルトの名無しさん
09/04/04 17:26:41
何か一冊マルチスレッドの本読むのおすすめする

510:デフォルトの名無しさん
09/04/05 04:12:53
class Hoge{
public:
 void End(){
 /*他のスレッド、シグナルハンドラとかから呼ばれる */
 Lock_.GetLock(); // 実際はRAII使ってるよ
 continuable_ = false;
 //その他のリソース会報処理
 }

 void Task(){
 // thread poolから実行されるタスク。
 Lock_.GetLock();
 if( continuable_ == false ){ return; }
 // IO処理とか色々非同期でやる
 }
};

なんか、フラグ使ってやるのが嫌なんだけど、
非同期で実行されるオペレーションをキャンセルさせる
スマートな方法ってない他にない?
この実装は間違ってる?

511:デフォルトの名無しさん
09/04/05 11:59:52
いいんじゃねえの。
スレッドを自発的に終了させるには
スレッド自身が何かをチェックしなけりゃならんし。

512:デフォルトの名無しさん
09/04/05 13:17:02
間違ってないし、フラグを使う方法は普通によくある

513:デフォルトの名無しさん
09/04/05 19:31:13
別プロセスにしてkill -9、これが最強。

514:デフォルトの名無しさん
09/04/05 19:36:59
せめてSIGTERMでやんわり殺してやれよ。

515:デフォルトの名無しさん
09/04/06 12:50:48
そうそう、せめて覚悟する時間くらいは与えてあげないと。
尤も、そうすると逆切れして殺しに来るかも試練が。

516:デフォルトの名無しさん
09/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を使用する。
といったような処理をするときに、特別にロックとか必要ですか。

517:デフォルトの名無しさん
09/04/09 00:58:51
>その後、スレッド間通信とかでスレッド1も2も上のa,b,c,dを使用した処理が完了したことをスレッド1,2に伝える。
これで同期取ってるから、そこをちゃんとすればよい。

518:デフォルトの名無しさん
09/04/09 01:47:33
弱い順序付けの場合だめな場合がありえるかもね

519:デフォルトの名無しさん
09/04/09 17:49:21
ねーよw

520:デフォルトの名無しさん
09/04/09 19:12:35
>>518
お前にとって同期ってなんだ?

521:デフォルトの名無しさん
09/04/09 19:52:20
グローバル変数keyに対して、他のスレッドで値を変更してループの続行、終了を決める場合に
while ( key ){ count++; }
というコード書くとコンパイラの最適化によって、無限ループになる可能性があるということですが、
while ( *pk ){ count++; }
のようにアドレスから参照しようとしても同じことになるのでしょうか。

522:デフォルトの名無しさん
09/04/09 20:54:12
わかんない。

つーか key を volatile にすりゃいいんでない?

523:デフォルトの名無しさん
09/04/09 21:01:11
>>521
うん。十分ありえる。

524:デフォルトの名無しさん
09/04/09 21:07:43
volatileで大丈夫そうですね。ありがとうございました。

525:デフォルトの名無しさん
09/04/12 11:51:26
マルチスレッドがどういうタイミングで割り込まれるのかわからないのですが
たとえば、if(++i == n) のコードなら
iをインクリメントしてからnを比較するまでの間で
割り込まれる可能性はあるんでしょうか?

526:デフォルトの名無しさん
09/04/12 12:30:10
あるよ
そもそも正しくインクリメントされることも保証されない
(CPUやコンパイル出力によるけど)

なぜなら、
(1) メモリからiの値を読み出す
(2) 値+1を計算する
(3) iの領域に計算結果を書き込む
という3ステップになる可能性があるから

527:デフォルトの名無しさん
09/04/12 12:43:39
>>526
そのステップ間で割り込まれるんですか、結構分割されるものなんですね
ありがとうございました

528:デフォルトの名無しさん
09/04/12 14:33:39
>>527
ただし、いつもそのように分割されるとは限らない。

529:デフォルトの名無しさん
09/04/13 22:54:34
volatile最強杉www

530:デフォルトの名無しさん
09/04/14 10:18:14
fread等でのデータ読み込みをシングルスレッドで実行する場合と
マルチスレッドで実行し、メインスレッドでは出来るだけ何もしない場合の速度は同程度になるものでしょうか?

531:デフォルトの名無しさん
09/04/14 10:27:26
>>530
速度は実測が基本。

たぶんその比較内容だと、激しく環境(ハードウェア、OS、コンパイラ)に依存する。

532:530
09/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 {
  // メインスレッド

 }
}

533:デフォルトの名無しさん
09/04/14 11:00:25
色々条件がよく判らんが、ここが一番判らん。
>100kb程度のデータで2倍、1mb程度だと4割程度の速度差になりました
2倍の速度差と4割の速度差ってどういう意味なんだか。
シングルスレッドに対してマルチスレッド版は2倍の速度差、つまり3倍所要時間が掛かったのか?

534:530
09/04/14 11:11:23
すみません、
所要時間
    シングル マルチ
100kb 0.013秒  0.025秒
1mb  0.100秒  0.140秒

です

535:デフォルトの名無しさん
09/04/14 11:17:22
>>530
マルチスレッドは、複数のことを同時にしたいときに使う技術なので、
そういう視点で選択した方がいいですよ。

ただ速度といっても、プライマリスレッドからストレージアクセスを
しているときキャンセルボタンを押したいんだけどその反応が鈍い、とか、
ストレージをアクセスしながらムービーを表示しているのだけれどコマ落ちする、とか、
単純コピーを速くしたい、では、とるべき手段に違いがありすぎます。

単にあるデータをストレージから読み込む処理だけに着目するなら、シンプルな
シングルスレッドの方が高速になることが多いと思います。
予め別のスレッドで利用するファイルを予測してアクセスし、キャッシュに入れておく
などというのはまた別の問題ですが。

536:530
09/04/14 11:33:30
>>535
ありがとうございます
極力シングルで動作できるような方法考えることにします

537:デフォルトの名無しさん
09/04/19 14:10:04
>>435
Phenomの2コアで2スレッド動かしたら2.2倍以上のスコアを叩き出した。
確かに2倍になる訳じゃないね。但し、配列をL2とL3に合わせて巧く分割
できた場合に限るけど。あと、OSのや他プロセスのボトルネックがある分
やっぱりマルチコアの方が早いね。実質90%でしか動けないシングルは倍
にしても180%だけど、90%+100%で動けるマルチコアだと実質190%で10%
ぐらい早くなる。

538:デフォルトの名無しさん
09/04/19 14:41:22
>>521
別にvolatile使わなくても問題なくね?
static int key=1;
void Thread0()
{
 key=0;//volatile指定が無い場合消失する可能性がある。
 Sleep(100);
 key=1;
}
void Thread1()
{
  while ( key ){ count++; }
}
こんな事でもしない限り無限ループにならんべや。
こんなコード書くことまず無いだろ。

それと、そもそも、グローバル変数使うなよ。

539:デフォルトの名無しさん
09/04/19 19:33:59
>>538
バカでしょ

540:デフォルトの名無しさん
09/04/19 22:08:19
>>538
まず、ネタなのかマジなのかを書いてくれ。

541:デフォルトの名無しさん
09/04/19 22:25:33
>>538
バカなの?死ぬの?

542:デフォルトの名無しさん
09/04/19 22:53:09
>>539-541
まじか。何で?

543:デフォルトの名無しさん
09/04/19 23:02:48
volatileを使うと排他制御しなくて
よくなるから必要

544:デフォルトの名無しさん
09/04/19 23:19:55
それは誤り

545:デフォルトの名無しさん
09/04/19 23:50:48
keyをテストする所にメモリバリア入れないと駄目じゃないかね

546:デフォルトの名無しさん
09/04/20 01:29:15
例えばJavaやC#などだと参照してる変数がvolatileだと期待通りに動くが、
そうじゃないとどうなるか分からんのじゃない?


547:デフォルトの名無しさん
09/04/20 15:54:13
>>543
volatileと排他制御はなんの関係もないぞ。
volatileは最適化の抑止で、せいぜい>>538の様な事や
レジスタだけでなくメモリ側にも変数を割り当てるぐらいだ。
そもそも、CやC++に排他制御なんて概念は無いから
クリティカルセクションなんかを使う他無い。
ちなみに、Javaは排他制御がかかるが、グローバル変数
と言っているからCかC++だ。もしかして、間違えてないか?

548:デフォルトの名無しさん
09/04/20 16:04:59
 で、>>539-541は、人をバカ呼ばわりしただけの
まっとうな理由あるんでしょうねぇ。まさか、Javaや
C#のvolatileしか知らない癖にバカにしてたなんて
恥ずかしい理由じゃありませんよねぇ当然。

549:デフォルトの名無しさん
09/04/20 16:23:18

J

550:デフォルトの名無しさん
09/04/20 19:35:31
【OS】WindowsXP SP3
【言語】C
ソース URLリンク(f50.aaa.livedoor.jp)
↑を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ファイルは生成されます。

よろしくお願いします。

551:デフォルトの名無しさん
09/04/20 20:32:51
>>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);

※スレッドなんて飛躍したものに手を出す前にこの手のエラーを自己解決できる
程度には言語機能を勉強し直した方がいい。

552:デフォルトの名無しさん
09/04/20 20:41:56
>>550
んだんだ、
それに、Cなんだから、void * が絡むときはキャストしない方が
素直で、読みやすいコードになる。
たとえば、
double *data = (double *) arg;
は、
double *data = arg;
としろ、ってことね。C++から来た人はこれをやりたがるのね。
C++だとこの場合にもキャストが必要だから。

乱文澄まそ

553:デフォルトの名無しさん
09/04/21 01:49:59
>>551
pthread_create(&a[i], NULL, (double *)thread_func, (double *)array);
は単に見落としていたようです。
お手数掛けて申し訳ないです。
直したらこの行のエラーは出なくなりました。

>>552
C++をやっていたわけではないのですが、配布されたソースコードの例にはこの形で書かれていたのでそれに準じて書きました。

そしてまだ14行目でエラーが出ますがpthread_selfの扱い方はそもそもこれでよいのでしょうか?
ちょろっと調べて出てきたものを使っただけなのでよく理解していません。

554:553
09/04/21 02:06:23
すみません、調べたらわかりました。
ただし他の問題が浮上しました。
pthread_t型をint型か何かに変換できないんですかね・・・。

555:デフォルトの名無しさん
09/04/21 02:31:33
>>554
pthread_tはポインタか構造体かなんかでしょ。
そもそも、別の型に代入しちゃいけない。
語のライブラリだと結構やろうと思えば別の型
に無理やり代入する事も出きるけどしちゃいけない、
内部に干渉しちゃいけないものがある。
大体識別値(discriptor)と呼ばれるものなんかがそう。
あと、初心者の内はメモリ操作が簡単にできる事が解って乱用する
人がいるがポインタのキャストはやたらめったらつかうもんじゃない。

てか、君の悩みはスレッド以前の問題だから、Cの初心者スレなんか
で質問しなさい。




556:デフォルトの名無しさん
09/04/21 20:37:55
言い方は気にくわないなw
小さい芽潰して楽しんでるふうにしかみえねーよ老害

>>554
pthread_tはunsinged longのtypedefだよ


557:デフォルトの名無しさん
09/04/21 21:56:02
>>556
何を言ってるんだおまえは? >>550のwarningを100回読み直してから出直してこい

558:デフォルトの名無しさん
09/04/22 00:05:38
>小さい芽潰して楽しんでるふうにしかみえねーよ老害
ふーん
芽をつぶして楽しんでて害なんだ
ふーん


559:デフォルトの名無しさん
09/04/22 01:49:54
そうなんじゃね、多分。

560:デフォルトの名無しさん
09/04/22 02:46:06
大人なんだからもっと仲良くしろよ

561:デフォルトの名無しさん
09/04/22 21:38:45
歯痛制御で俺の虫歯を何とかしてくれ

562:デフォルトの名無しさん
09/04/22 22:28:22
チュイーン ギキィィーー

563:555
09/04/22 22:56:29
>>556
 俺、21歳なんだが。3D関連でC++始めて5年以上にはなるが、
そうか俺も、もう老害か・・・。

564:デフォルトの名無しさん
09/04/23 00:01:02
>>561
本業歯医者の趣味グラマだけど何か用?

565:デフォルトの名無しさん
09/04/23 02:10:25
>>564
医者の趣味グラマっておおいな。
LHAも医者だし猫プロの筆者も医者。
しかも、本業より優秀そうなんだよな・・・。

566:デフォルトの名無しさん
09/04/23 02:33:52
本当は工学系にいきたかったのに、
なまじっか頭いいと医療系への進学を勧められちゃう奴って多いからな

567:デフォルトの名無しさん
09/04/23 09:19:51
いつも思うんだけど、歯科治療技術も日々発展してるだろうから
古い医者より新しいところの方がいいのかねえ

568:デフォルトの名無しさん
09/04/23 11:19:32
ジャストシステムのスタートアップにも医学生がいたな。
人間って本当に不公平にできてるよ。

569:デフォルトの名無しさん
09/04/23 12:48:15
>>564
予約時間の十分前には歯科に着いているのに
待合室で一時間待たされ、診察室に通されたと思ったら
また三十分以上待たされるのを何とかしてくれ

どう見ても歯科医と歯科助手がデッドロックを起こしているようでなかなか回ってこない

570:デフォルトの名無しさん
09/04/23 19:35:34
>>569
誰がうまいこと言えとw
デッドロックは言いえて妙だったわ。

571:デフォルトの名無しさん
09/04/23 23:58:32
>>567
少なくとも、レントゲン撮影したら「現像するから日を改めて」なんてところは止めた方がいい。
今時、治療椅子ごとに端末があってそこで見られるのが当たり前。

572:デフォルトの名無しさん
09/04/24 09:00:21
>>571
端末は無いけど、数分で現像したフィルムができるのが普通じゃない?
2,30年前からそうだったと思うんだけど

573:デフォルトの名無しさん
09/04/24 09:44:28
いい加減にしとけよ

574:デフォルトの名無しさん
09/04/24 11:57:45
マルチスレッドと減増
関係あっても、遠い存在のような


575:デフォルトの名無しさん
09/04/24 17:51:20
>>556
老害ではなく、基地害だ


576:デフォルトの名無しさん
09/05/02 22:30:20
俺の日記帳
今日は5月2日です。
何してるの?

577:デフォルトの名無しさん
09/05/04 23:25:22
C++0xではマルチスレッドプログラムを組むのは
容易になるのであろうか

578:デフォルトの名無しさん
09/05/04 23:26:23
C++でマルチスレッドは危険ですよ

579:デフォルトの名無しさん
09/05/04 23:36:49
>>578
Win32本では平気でマルチスレッド走らせる例が書いてあるけど
デッドロックについても詳しく説明してある

580:デフォルトの名無しさん
09/05/05 04:20:22
>>579
なんだその会話になってないレスは

581:デフォルトの名無しさん
09/05/05 06:50:37
CやC++の言語レベルではマルチスレッドについての取り決めはない。
ライブラリ(pthreadなど)やプラットフォーム(osやハードウェア)や実装(コンパイラ)レベルで、
扱いが決められているので、そういったものの前提抜きでマルチスレッドは語れない。

582:デフォルトの名無しさん
09/05/05 09:33:35
メモリモデルの仮定が入っちゃうからやりにくいだろうなあ

583:デフォルトの名無しさん
09/05/05 09:58:42
>577
concurrency 周りが大幅に強化されてるんで、恐らくは。

584:デフォルトの名無しさん
09/05/09 12:04:34
マルチスレッドにする利点は何?
複数の処理を同時に走らせることができるなんて妄想は無しで。

585:デフォルトの名無しさん
09/05/09 12:10:53
世界の全てが妄想なので、答えは消滅しました。

586:デフォルトの名無しさん
09/05/09 12:12:54
複数の処理を同時に走らせることができる、妄想で無しに。

587:デフォルトの名無しさん
09/05/09 13:11:27
個人的には>>584が何故「複数の処理を同時に走らせることができる」ことが妄想だなんて妄想を抱いたのか知りたい希ガス。
マルチスレッドの利点は全てそこから派生しているはずなのだが。

588:デフォルトの名無しさん
09/05/09 13:25:02
>>587
TSSは同時ではないとでも言いたいんじゃないか?

589:デフォルトの名無しさん
09/05/09 15:05:51
>複数の処理を同時に走らせることができる
ってのはいわゆる手段なんで。
大元の目的は「暇をもてあましてるリソースを有効活用する」だな。
マルチスレッドはCPUがヒマしてる場合の、GPGPUはGPUがヒマしてる場合の手段だな。

>584がどんな妄想してるか迄はわからんが。


590:デフォルトの名無しさん
09/05/09 15:53:09
>>589
それ以外にもあるぞ。むしろプログラマ的にいちばんうれしいのは、コンテキストの異なる処理を明示的な切り替え無しに同居させられることじゃなかろうか。
重い処理を別スレッドでガリガリ処理しつつ、その進行状況をGUIで表示するとか。

591:デフォルトの名無しさん
09/05/09 23:10:29
ハァ?
すべてをファイル・デバイスにしてそれをpollすればシングルスレッドで可能ですが何か?

592:デフォルトの名無しさん
09/05/09 23:20:27
スレタイ無視

593:デフォルトの名無しさん
09/05/09 23:39:00
昔のunixはスレッドなしでもfork/execだけでたいていの事はやれてたな。

594:デフォルトの名無しさん
09/05/10 05:27:53
>>591
ちょっと話違うが、Androidのセンサーまわりの設計もそんな感じ。
だが、そのファイルディスクリプタをもらう元が、1つしかなかったり
してセンサーごとにドライバが作れない。

1.0のころはモジュール化すらされてなかったり、1.5になっても
いまだダセー設計だし。設計したやつの顔が見たいな。

595:デフォルトの名無しさん
09/05/10 08:32:10
ドライバといった低レベルI/O処理の基本はスレッドより割り込み。
割り込みがないディバイスだとポーリングも使うけど。

596:デフォルトの名無しさん
09/05/10 09:07:05
何かの処理で待ちも含めてぐるぐる回りながら、他の処理も同時にやりたい、とかいう場合に
いちいち処理を細切れにしてpollを含むメインループから呼び出す形に縛られるのは面倒だわな。

マジレスすると。

597:デフォルトの名無しさん
09/05/10 10:29:43
>>593
でも今はマルチスレッドがサポートされているということは、その煩雑な方式では力不足だったってことだよね。

598:デフォルトの名無しさん
09/05/10 10:51:01
今のところは、
やることを細切れにできるようにしておいて
pollするスレッド(大半の時間は待機)が
少数のワーカーに仕事を振り分け
ワーカーはひたすら仕事だけを待ちつづける、というやり方が
I/O待ちやマルチCPU(コア)を有効に生かせ、
メモリやコンテキストスイッチのロスも少なく出来ると言われてるな。

599:デフォルトの名無しさん
09/05/10 10:56:07
開発効率という効率を無視すれば、それがベストだねw

600:デフォルトの名無しさん
09/05/10 13:17:08
OSのスケジューラをエミュレートしてるだけのような

601:デフォルトの名無しさん
09/05/10 15:04:43
コア数を大幅に越えるスレッドを生成すると、
コンテキストスイッチのせいでむしろ性能が低下する。ってのは本当なの?
実測して確かめたいんだけど、どういうコードを書けばいいのか解らん。
えろいひと教えて

602:デフォルトの名無しさん
09/05/10 15:07:34
スレッドプールにすりゃ解決よ

603:デフォルトの名無しさん
09/05/10 15:11:52
>>601
本当
スレッドに手を出した頃それに嵌ったことがある
各スレッドの同期にmutex/conditionを使う形で大量のスレッド作って試してみればわかるよ
むやみにスレッド数を多くするのはそもそも設計が良くないです

604:デフォルトの名無しさん
09/05/10 16:01:38
オーバーヘッドが増大する。 スレッドの多さは関係無し。 
たとえば1ms以内で終了するスレッドを生成すれば効率悪い。

605:デフォルトの名無しさん
09/05/10 16:02:56
>>601
スレッドって、一般にはコンテキストスイッチが入らない
(だから軽い)というモノだろう?

原理的には性能低下は無い。
但し、実際のところコア間でキャッシュを共有してたり、
メモリバスを共有してるので、複数のコアを同時に使うことで
シングルコアよりも性能低下することはありうる。


606:デフォルトの名無しさん
09/05/10 16:22:26
マルチスレッドのプログラム組んでるんでて
ある変数に複数のスレッドから同時にアクセスできるときは
排他的処理しないとだめ?
というか たぶん今のエラーはそうだろうと思う

607:デフォルトの名無しさん
09/05/10 16:24:10
複数スレッドからアクセスしても、OSがエラーはいたことはないな。
値は、ぶっ壊れるけどね。

608:デフォルトの名無しさん
09/05/10 16:28:00
読むだけなら問題ない

609:デフォルトの名無しさん
09/05/10 16:29:54
読み書きしても、エラーでたことない。 
たとえばグローバルsum=0に、複数スレッドから足し算してもエラーで停止しないが。

610:デフォルトの名無しさん
09/05/10 16:31:49
どういった場合に、メモリーエラーが起こるのかが知りたい。

611:デフォルトの名無しさん
09/05/10 16:33:36
>>605
> スレッドって、一般にはコンテキストスイッチが入らない

今コンキストスイッチしないのって絶滅危惧種だろ

612:デフォルトの名無しさん
09/05/10 16:36:05
なるほど
変数がスタックで削除したり追加したりだからダメなのか

613:デフォルトの名無しさん
09/05/10 18:23:53
>>605
マテ、スレッドでもコンテキストスイッチは発生するぞ。
スレッドが(プロセスに比べて)軽いのは、スタックとレジスタだけ
切り替えれば済む(これもコンテキストの切り替えだ)からであって、
コンテキストスイッチそのものが行われないからじゃない。

614:デフォルトの名無しさん
09/05/10 18:26:42
1CPUの場合はタイムスライスだけになるから減らないが、
CPUが複数ならスイッチ自体を減らせるという話じゃないかい。


615:デフォルトの名無しさん
09/05/10 22:05:51
>>613
ユーザランドでのスレッド実装だと
カーネルモードに入る回数が少なくて済むとかじゃね?

というかこの手のは、何が重いか時代により激しく違ってくるから
一般論といってもそれが何時のものかによるなあ

616:デフォルトの名無しさん
09/05/11 21:55:27
昔を語るのが一般とは思えない。

617:601
09/05/11 22:46:47
時代によって変わるもんなのか。
レジスタ、スタックの退避とか、カーネルに入って出てくる処理とかが重いのかとかとか思ってたんだけど。
fiberは軽いよ。とか聞くけど、それはおいといて。
>>603
mutexとか排他は考えないで、純粋に「コンテキストスイッチ」処理がどれくらい重いもんなのか
図りたい。
linuxでpthread使ってやろうと思ってるんだけど、どんなコードを書けばいいんだろ
単純に0から0xffffffffまで足す処理をシングルスレッドでやるか、
0~0xffを足す処理を0x1010101個のスレッド立てて計算させて、どっちが早いか。とか?<そりゃないだろって

618:デフォルトの名無しさん
09/05/11 22:57:13
>>617
CPUの数だけ分割するのが速い

619:デフォルトの名無しさん
09/05/11 23:28:58
例えば
20ms(OS次第)以上かかる計算処理を一つのJobとして
Job計10000個をキューに入れる。
スレッドをプールしておいて、各スレッドはキューからJobを取り出してひたすら実行する。
この時、プールするスレッド数をプロセッサ数と同数の場合と2000個の場合とで実行時間を計る。

現実的には、スタック領域以外にも
各スレッドで多少の独立したメモリ領域は使うことが多いと思われるので
ただの(レジスタやスタックで納まる)計算はではなく、
16Kなり64Kなりの領域をスレッド毎に確保しておいて
その内部の値を使った計算とする。

等というのはどうだろうか。

620:デフォルトの名無しさん
09/05/11 23:39:02
別にキューに入れる必要無いな。
同じことを繰り返すだけなんだから、CASを使ったカウントアップだけして
一定の数字になったらスレッド終了で充分か。
これなら、共有メモリを使えば、プロセスとの比較も出来る。

ただ、スレッドは「スタートのシグナル」を全部同時に出すことが出来るけど
プロセスだとどうなんだろ。全然知らない。

621:デフォルトの名無しさん
09/05/21 21:54:47
昔はPVM、今の時代はMPI
そしてOpenMPとMPIのハイブリッド実行が主流なのだろうか

622:デフォルトの名無しさん
09/05/21 22:39:20
>同じことを繰り返すだけなんだから、CASを使ったカウントアップだけして
>一定の数字になったらスレッド終了で充分か。

こんな非現実的な処理の時間を計測して何の意味があるわけ?


623:デフォルトの名無しさん
09/05/21 22:40:10
おそらくプロセッサ(コア)が増えれば増えるほど遅くなると思うけど。


624:デフォルトの名無しさん
09/05/21 22:44:10
ああ読み違えてたすまんのう
単に処理繰り返し数のカウントで使うだけってことね…


625:デフォルトの名無しさん
09/05/21 23:23:37
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
09/05/22 00:14:01
追記です。

そもそもGetKeyboardState()はメッセージキューに溜まったものを見るものであって、
新しく生成したスレッドでは、肝心のメッセージを取得することができない、、、
というあたりまではなんとなく理解できました

ちなみにやりたいことはキー情報の一括取得(できればリアルタイムの)です。
(GetAsyncKeyState()では1つ1つしか取れないので・・・
引き続き、解決策などありましたら、お願いします

627:626
09/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()でも一応取得できました。
荒療治な気がしますが・・・
もっと良い方法などありましたら、お願いします

628: ◆0uxK91AxII
09/05/22 02:41:05
>>617
適当なsystemcallを行い、前後でCPUのtimestampでも読めば、
最も軽い場合については、調べられる。

>>625
DirectInputを使うとか。

629:デフォルトの名無しさん
09/05/22 03:20:02
>>627
GetKeyboardState()が使用する入力情報は、スレッドごとにある。
AttachThreadInput()はそれを共有させるためのAPIなので、その目的なら
それが一番適切な方法。
ただ、フォアグラウンドウインドウにAttachしてるのは間違いじゃないか?

GetAsyncKeyState()は自分のプロセスが非アクティブでもキー情報を取得できるAPI。
自プロセスの別スレッドでキー入力を拾う目的で使うのは、使えないことはないが
自分がアクティブかどうかの確認が必要で面倒。

630:626
09/05/22 04:59:32
>>628
DirectInputは同じような理由で取得できず...(・ω・

>>629
問題なく動いてるんで今の形(フォアグラウンド)で放置してたんですが、
ウインドウハンドルって引数以外で取得できるんでしょうか

631:デフォルトの名無しさん
09/05/22 06:02:44
>>630
GetWindowThreadProcessIdもGetForegroundWindowもいらない。
beginthreadexを呼んだスレッドで、そのままAttachするだけ。

そもそも、自分のウインドウを取得するのにGetForegroundWindowを
使うこと自体おかしい。
アプリケーションを起動したら必ずフォアグラウンドになるわけではないし。

632:626
09/05/22 15:13:54
確かにかなり回りくどいことしてました。

ただ、Attachの処理は生成処理の直下で一度だけ呼び出しても機能しなかったので、
beginthreadexを呼んだスレッドID(MainThreadId)だけをセーブして、
>>627と同じ場所で「AttachThreadInput(CurrentThreadId, MainThreadId, TRUE );」という形にまとめました。

633:デフォルトの名無しさん
09/05/22 16:18:42
新しく作成されたスレッドはGUI関連のAPIを呼び出すまでメッセージキュー等が
作成されないから、スレッド作成直後だと失敗するね。

新しいスレッドでウインドウを持っているならウインドウ作成後、ウインドウが
なければPeekMessageの空呼び出しの後でAttachがいいかな。

634:???
09/05/22 16:58:17
アセンブリ言語によるプログラミングで、1+2+3+・・・・+10と、1から10までの足し算をするプログラムはどのようなものになりますか?

16進数表現です。

635:デフォルトの名無しさん
09/05/22 17:14:22
まずは正しいスレッドを探すことからだな

636:デフォルトの名無しさん
09/06/09 21:56:35
質問です。

constで定義されている、読み込み専用の変数に対して
複数のスレッドがアクセスするとき、同期(クリティカルセクションなど)は
必要ありますか?

637:デフォルトの名無しさん
09/06/10 07:47:41
よっぽど変なハードウェアでない限り
要りません。

638:デフォルトの名無しさん
09/06/10 19:52:05
volatileで十分w

639:デフォルトの名無しさん
09/06/13 18:02:44
volatile使うやつは情弱

640:デフォルトの名無しさん
09/06/26 02:20:50
WindowsXP、VC2008EEの環境で作っています。
>>636の質問とかぶるのですが、1つのコンテナを複数のスレッドからイテレータでアクセス(読み込みのみで書き込みはない)しています。
実行時にイテレータを使った部分(直接使用しているのはSTL)でエラーが出て強制終了になってしまいます。
試しにスレッドを1つにしたらエラーは出ませんでした。
どういった原因が考えられるでしょうか?

641:デフォルトの名無しさん
09/06/26 03:48:25
そのSTL実装がスレッドセーフじゃないんでしょ。
機能としての読み込みであっても、内部で書き込みしていて競合する場合もあるだろう。
アトミックなところまでスレッドセーフが保証できないならロックすべき。

642:デフォルトの名無しさん
09/06/26 04:59:50
>>641
なるほど・・。
マルチスレッドは難しいですね。

643:デフォルトの名無しさん
09/07/04 11:06:03
>>640
単純に興味本位なんだが、const_iterator でも駄目なの?

644:デフォルトの名無しさん
09/07/04 11:09:45
最近マルチスレッド環境下でスレッド毎にプールを持つ
malloc() 実装がよくあるよね? 諸々の事情でそれが使
えない場合、アプリ側で出来る事ってある?

OO 的に小さなオブジェクトを生成/破棄するんだけど、
スレッドを跨って破棄を委譲するケースもあるんだ。で
も、単純にメモリ管理スレッド作っても過去の効率の悪
い malloc() 実装の焼き直しみたいになって多分効率悪
いと思うんだよね…。

645:デフォルトの名無しさん
09/07/04 11:16:05
アプリ側でそういう実装をやってるのはあっても動作環境側でそんな実装やってるの在るか?
複数のプール持つ実装はあるだろうけどスレッド固有になるような実装してたらそれこそスレッド跨げないし

646:デフォルトの名無しさん
09/07/04 11:49:37
>>645
ああ、中央ヒープはあるんだよ。でも、スレッド毎にも
管理されるよね? 多分細かくスレッドが生成/破棄され
るようなケースではかなり改善されるんだと思う。

URLリンク(goog-perftools.sourceforge.net)
↑Google の tcmalloc はコアヒープとスレッド毎のキャッ
シュという形で実装されている。

URLリンク(people.freebsd.org)
↑FreeBSd の jemalloc もスレッド毎に管理されてるみ
たい(TLS)だけど、要求されるサイズによって割り当て
部を買えるような話がある。

でも、やっぱりスレッド跨ると古い malloc() と同じ話?
うーん、ここまで来ると「どのコアで動くか」まで関連
するかなぁ…。

647:デフォルトの名無しさん
09/07/04 12:19:54
jemallocは自分が割り当てられたarenaをヒープのメタデータにつっこんでおいてfree時にはそこから解放するようになってる
割り当てはそれこそぽんぽん次のarenaをTLDに結ぶけどさ
そうでもしなきゃFreeBSDのデフォルトになれてない

完全に一切ロックせずスレッド固有のヒープにするなんてのはアプリ内の実装でなきゃ出来んよ

648:デフォルトの名無しさん
09/07/04 12:35:06
いやだからそのアプロ側でどうすんの? ってのを聞いてるわけで…。

649:デフォルトの名無しさん
09/07/04 12:43:37
一体何を心配して居るんだお前は?

650:デフォルトの名無しさん
09/07/04 13:46:18
小さいメモリ大量なら、固定長のバッファをリンクリストかなんかに
つないでおいて、利用すればいいじゃん。malloc, freeよか速い
だろ。

651:デフォルトの名無しさん
09/07/04 17:04:33
>>644
mallocにしてはやりすぎじゃない?
C++のallocatorならそういうのもあると思う。

652:デフォルトの名無しさん
09/07/06 15:13:06
とりあえず何も考えず素直に作って問題が出たら詳細に
考えることにするよ。一応アロケータ的なインタフェイ
ス挟んでるから後からでもなんとかなると思う。

malloc/free に時間かかってる/かかってないの判定と
かは gprof 辺りで大丈夫なんだっけ?

653:デフォルトの名無しさん
09/07/07 13:30:13
>>652
一応gprofでも判らなくもないと思う。呼び出し回数は記録されないけどね。
使える環境なら、vtuneみたいなツールを使う方が(当然)判りやすい。

654:デフォルトの名無しさん
09/08/04 10:34:44
pthreadで、デタッチ状態のスレッドをポコポコつくったりしてるとき
生成したスレッドのうち今何個生きているかを知りたいんだけど
pthread_hogehoge() で何か知れるような手段用意されてたっけ?

655:デフォルトの名無しさん
09/08/04 11:52:30
マルスレage

656:デフォルトの名無しさん
09/08/04 12:00:52
無いんじゃない?atomicなカウンタでも使えばいいじゃん。

657:デフォルトの名無しさん
09/08/04 17:07:08
>>656
もしそういうカウンタがもうあるなら再車輪せずに済むかな、と。

658:デフォルトの名無しさん
09/08/04 18:51:12
Linuxの話だけど、この件については他でも同じ
URLリンク(www.yolinux.com)
A thread does not maintain a list of created threads, nor does it know the thread that created it.

スレッド数だけであれば、psでスレッドの情報出すときと同じ方法でできる?

659:デフォルトの名無しさん
09/08/04 21:20:30
>>658
pstreeとかのソース読んだからまあ大体のことはできるんだけど
そうか、管理しないことをウリにしてんのか。仕方ないなぁ。
スレッド管理はOS任せか~。そりゃそうだよなぁ。

660:デフォルトの名無しさん
09/08/09 15:09:11
Javaで複数のインスタンスのAというメソッドに同期をかけたい場合は、
どうすればよいのでしょうか?

661:デフォルトの名無しさん
09/08/09 15:52:00
>>660
同期は(メソッドにかけるものじゃなくて)メソッドが
アクセスするリソース(メモリやディスク)にかけるものだよ。
あと「同期」はスレッド間でイベントの発生待ち&発生通知を
実現する場合に使われる単語。もしもスレッド間で
(メソッドを通した)リソースへのアクセスの競合を避けるのが
目的なら、「排他制御(あるいはロック)」という単語を使うのが適切。

で、質問が(後者の)排他制御を実現する場合に関するもとすれば、
各インスタンスのメソッドAで(アクセスしたいリソースへの)
排他制御を実装するコードを単純に書けばいい、というのがレスになる。

もしも各インスタンスのクラスが同一ではないため、複数クラスで
メソッドのコードを変更するのはプログラム構造が複雑になると
考えているなら、たとえば以下のようなヒントが参考になるかもしれない。

・コールバック機構を利用して並行処理時に発生するバグを防止する
  URLリンク(japan.internet.com)

662:デフォルトの名無しさん
09/08/09 16:02:51
>>661
ご回答ありがとうございます。
プロセス起動時の初期処理用メソッド(DBからマスタを取得し、キャッシュする)に同期をかけたいと思っていました。
お返事どおり、メソッドではなく、リソース(オブジェクト)に対して、ロックをかけるのが正しいですね。
キャッシュクラスをシングルトンで実装し、同期化をさせることにします。

663:デフォルトの名無しさん
09/08/11 00:33:30
メソッドにsynchronizedを付けると、同一インスタンスで1つのスレッドしか実行できないということですか?
複数インスタンスあれば、実行できてしまうのでしょうか?

664:デフォルトの名無しさん
09/08/11 00:50:50
できてしまいます

665:デフォルトの名無しさん
09/08/12 22:09:06
staticメソッドなら大丈夫。
synchronized(Hoge.class) とか

666:デフォルトの名無しさん
09/08/12 22:56:58
>>665
> staticメソッドなら大丈夫。
> synchronized(Hoge.class) とか

そこまで書くならstaticメソッドじゃなくてもいいじゃん

667:デフォルトの名無しさん
09/08/16 00:34:07
マルチスレッド環境でマスタデータをDBからとってきて、HashMapかListなどに持たせるのは
問題ないのでしょうか?
基本的にJavaプロセスを起動している間にマスタデータが変更されることはない環境です。

668:デフォルトの名無しさん
09/08/16 00:34:56
667です。
データを持たせるHashMapかListはクラス変数で持たせたいのですが。

669:デフォルトの名無しさん
09/08/16 00:37:29
情報不足
どういう問題がありえると思ってるんだ?

670:デフォルトの名無しさん
09/08/16 01:02:48
すみません。
HashMapとかListに数千件というマスタ情報を持たせるのがおかしくないのかという点と、
HashMapやListにデータを追加するときはロックをかけますが、データを取得するときは
ロックをかけなくても問題ないかを知りたいです。


671:デフォルトの名無しさん
09/08/16 01:16:29
>>670
ハッシュなんてもんはメモリが許すなら数万件程度は入る事を前提で作るんだが


672:デフォルトの名無しさん
09/08/16 01:37:04
>>670
(すでに別の方法で同期済み等で) 追加と取得が同時には起きないと判っているなら、取得同士の間のロックは不要
追加と取得が同時に起きるかもしれないなら、取得にもロックは必要

673:デフォルトの名無しさん
09/08/16 06:35:50
通信とかどうでもいいから普通にマルチコアに特化したライブラリってないのさ?

674:デフォルトの名無しさん
09/08/16 08:59:53
つintel TBB

675:デフォルトの名無しさん
09/08/16 09:49:44
>>673
スレッド間通信が無くても役に立つマルチスレッドアプリとは何者?

676:デフォルトの名無しさん
09/08/16 21:13:28
ブルートフォースとか

677:デフォルトの名無しさん
09/08/17 10:00:56
>>675
サーバとか

678:デフォルトの名無しさん
09/08/18 12:29:42
pthreadでPSで表示したときのスレッド名を変える方法ってありますか?

679:デフォルトの名無しさん
09/08/20 11:14:51
ないんじゃない?

680:デフォルトの名無しさん
09/08/27 19:59:12
PR_SET_NAMEすればいいんじゃない?

681:デフォルトの名無しさん
09/08/28 15:32:43
Cでマルチスレッドのプログラミングで
ふたつのスレッドの時間的な同期をとって
同時に同じファイルを開くにはどのように書けばよいですか

682:デフォルトの名無しさん
09/08/28 16:04:42
>>681
そんなことできるんですか

683:デフォルトの名無しさん
09/08/28 16:11:59
>>681
その発想はなかった

684:デフォルトの名無しさん
09/08/28 16:12:05
>>680
ありがとう。とても役に立った。

685:682
09/08/28 16:18:17
>>681
2つのスレッドから共通のモジュールを介してファイルにアクセスするようにしてはどうですか
2つのスレッドからは1つのファイルを開いているように見せつつ,
そのアクセス(読み書き)先の実体であるモジュールの中で排他制御するんです

686:デフォルトの名無しさん
09/08/28 17:14:56
対象OSにどういった同期手段が用意されているかによる
どの程度同時性を求めるかにもよるし、それはつまり何のために同時でなきゃならないのかにもよる


687:デフォルトの名無しさん
09/08/28 20:01:11
>>681
日本語の文章がちゃんと書けない人はプログラミングも出来ない。
by 竹内

688:デフォルトの名無しさん
09/08/28 20:10:31
>>686
これ、日本語が致命的に下手なだけで、要点は
ただ排他制御したいってことだろ

689:デフォルトの名無しさん
09/08/28 20:20:01
時間的な同期を取るってんだから、「同時」の意味が違うかもしれんぞ

690:デフォルトの名無しさん
09/08/28 22:58:07
日本語が下手ではなく、
頭の中で思考の同期が取れてないのでは。

691:デフォルトの名無しさん
09/08/29 02:53:56
排他制御しないって意味かもしれんぞ

692:デフォルトの名無しさん
09/08/29 06:04:35
まぁ、>>681がマルチスレッドでプログラミングすべきでないことだけは間違いないな…

693:デフォルトの名無しさん
09/08/29 08:12:32
>>681
同時に開く保証はできない。
「ほぼ同じ頃に開くことができるかもしれない」が限度

694:デフォルトの名無しさん
09/08/29 08:32:21
2スレッドをイベント待ちにしてから、同時に起こすのかと思った。

695:デフォルトの名無しさん
09/08/29 09:00:31
マルチスレッドプログラムでのよくある落とし穴をまとめたサイトってどこかにない?

696:デフォルトの名無しさん
09/08/29 09:36:25
>>695
URLリンク(www.itmedia.co.jp)
まんまのがあるではないか。

>Windowsプログラマーでスレッドをいちども使ったことがない人はいないだろう。

一瞬それはないだろうと思ったがスレッド使わなきゃWindowsのプログラムは作れぬなw

697:デフォルトの名無しさん
09/08/29 11:12:44
シングルはあるよな

698:デフォルトの名無しさん
09/08/29 11:14:07
まぁ「プログラムなんてとりあえず動けばいいや」と考えている奴は大抵マルチスレッド関連でバグ出してハマるしな。

699:デフォルトの名無しさん
09/08/29 11:19:51
>>698
そういうのは未だ救いようがあるが自分の痛さに気づいていない
プログラマーは救いようが無い。

700:696
09/08/29 11:39:02
よく見たらゴミ記事であるな。
参考にしないほうが良い。スマヌ Orz

701:696
09/08/29 11:47:41
ゴミ記事って言うのは酷すぎた。。
前提知識のない初心者が見ると混乱すると言うのが正しい。

702:デフォルトの名無しさん
09/08/29 18:11:28
冒頭の四行くらいで日本語も問題切り分けも怪しく感じたから流し読みしたけど
どうでもよさそうな記事だった

703:デフォルトの名無しさん
09/08/29 21:52:57
シングルトン実装から始まって愚駄ぐだになって終わってると。

704:名無しさん@そうだ選挙に行こう
09/08/30 10:25:00
>>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;の後じゃないの?

705:名無しさん@そうだ選挙に行こう
09/08/30 13:05:55
_Valueの代入はlockの中にあるから、_Valueが更新される前にlockを抜けるわけはない
第2のスレッドがやってきて外側のif(_Value==null)を見たときに、
もし_Valueがまだnullならlockに引っかかるから最初のスレッドが更新を完全に終えるまで待たされるので問題ない (lock/unlock自体がメモリバリアになる)
問題は_Valueがすでにnullでなかった場合、_
Valueは新しいオブジェクトを指しているけれども_Valueの中のフィールドはまだ更新されてない、という事態が起きうる (メモリの書き込み順序は勝手に並び替えられるので)
それを防ぐためにメモリバリアを挟んで、_Valueが更新されるよりも前に_Valueの中身が更新されることを保証している

706:名無しさん@そうだ選挙に行こう
09/08/30 13:28:19
_Valueが更新されるよりも前に_Valueが参照されないことを保証している

707:名無しさん@そうだ選挙に行こう
09/08/30 13:35:51
_Valueへのアクセスは同期されてないから、lock中で_Valueが更新された直後から
他スレッドからAが使えるようになる。
でも

Aの構築
_Valueの更新
Aの構築の結果がAのフィールドに反映される

となる可能性があり、不完全な状態のAが使われる可能性がある。
だからAをnewした後にThread.MemoryBarrier()してから_Valueに代入する。
_Valueへの代入はlockを抜ける段階で保証される。

ということか。
勉強になった、ありがとう。

708:名無しさん@そうだ選挙に行こう
09/08/30 13:39:37
一応はっておく
URLリンク(www.ibm.com)

709:デフォルトの名無しさん
09/09/01 20:32:30
クアッドコアを使った並列処理を
MFCでのマルチスレッドでやろうとしておりますが、
シングルコアのときと同じマルチスレッドのプログラムでも
4つのコアを利用した並列処理になるんでしょうか?


710:デフォルトの名無しさん
09/09/01 20:34:22
なるよ

711:デフォルトの名無しさん
09/09/01 20:38:55
>>710
そうっすか!ならよかったです。

712:デフォルトの名無しさん
09/09/01 21:08:29
erlang

713:デフォルトの名無しさん
09/09/02 00:40:31
>>709
MFCには詳しくないけどシングルコアで問題なく動いてたMTセーフのつもりの
プログラムがマルチコアにもってくと異常動作することはそれなりにあるん
じゃないの?int型への代入・参照を非同期でやってたりするプログラムだと。


714:デフォルトの名無しさん
09/09/02 01:07:14
>>713
何故int? 64bit整数ならわからんでもないけど。

715:デフォルトの名無しさん
09/09/02 01:11:11
つーかそんなことを質問してるわけじゃねーし。
言ってみたかっただけだろ。

716:デフォルトの名無しさん
09/09/02 01:18:05
intでもread-modify-writeはatomicじゃないぞx86は(も)

717:デフォルトの名無しさん
09/09/02 01:18:42
>>709
なる。OSネイティブのスレッドは、明示的に指定しない限り、複数のコアに分散される。
とは言え、排他制御が適切でないと、各コアを有効に利用できないけど。

718:デフォルトの名無しさん
09/09/02 01:27:46
>>716
いや、それだったらそもそもデータ型問わんのでは。

719:デフォルトの名無しさん
09/09/02 01:33:30
いやいや、おまいら、それ以前にそれはスレッドセーフと呼ばないのでは。


720:デフォルトの名無しさん
09/09/02 02:19:59
>>718
64bitなら、と言ってるから、マシンワードならアトミックと思ってるのかなと思った

721:デフォルトの名無しさん
09/09/02 03:38:51
volatile

722:デフォルトの名無しさん
09/09/02 06:06:12
volatileがどうかしたか?

723:デフォルトの名無しさん
09/09/02 09:42:27
vottakle

724:デフォルトの名無しさん
09/09/02 13:14:01
明白な答えが、ここで出せるわけ無いんだから。
あなたが欲しいのは同意なんじゃないの?だから荒れる。

725:デフォルトの名無しさん
09/09/02 13:37:33
>>724
独り言が言いたいだけだ、とかでないなら
最低限アンカーくらい書いたら?

726:デフォルトの名無しさん
09/09/02 13:55:09
>>725
ごめんめっちゃ誤爆

727:デフォルトの名無しさん
09/09/02 13:57:38
        ∧∧
       ヽ(・ω・)/   ズコー
      \(.\ ノ
    、ハ,,、  ̄
     ̄

728:デフォルトの名無しさん
09/09/02 14:27:31
>>696
いまひとつ怪しい記事だな。
だいたい今の.NETじゃ前提が変わりすぎてて、役にたたないどころか害のが多い気がするし。


729:デフォルトの名無しさん
09/09/02 21:22:08
>>720
64bitを持ち出したのは、32bitマシン(あるいは32bitモード)だと、単一の書き込み/読み出しでも競合すると値が壊れる可能性があるから。
(最初の32bitが書き込み前の、次の32bitが書き込み後の値を読み出す可能性がある)
マシンワード以下なら、順序が入れ替わることはあっても値が壊れることはないと思ってるんだけど、それもあてにならない?
あと、x86系だと、ワード境界をまたぐ読み書きがどうなるかがよくわからない。

730:デフォルトの名無しさん
09/09/02 21:40:02
P6以降はキャッシュアラインドなマシンワードのreadやwriteはアトミックだよ
read-modify-writeはLOCK#がassertされないとアトミックじゃないよ
xchg命令は昔からLOCK#がassertされる仕様だからアトミックだよ

コンパイラも含めた挙動はこの辺も参考にするといいよ
URLリンク(msdn.microsoft.com)(VS.85).aspx

731:デフォルトの名無しさん
09/09/02 21:48:23
URLリンク(www.intel.com)
ここの 8.1 LOCKED ATOMIC OPERATIONS を嫁

732:デフォルトの名無しさん
09/09/02 22:01:55
>>729

>マシンワード以下なら、順序が入れ替わることはあっても値が壊れることはないと思ってるんだけど、それもあてにならない?

w

733:デフォルトの名無しさん
09/09/03 00:09:10
The Art of Multiprocessor Programming
糞本だなぁ



734:デフォルトの名無しさん
09/09/03 03:59:45
volatile

735:デフォルトの名無しさん
09/09/03 05:34:09
volatile変数へのアクセスのアトミック性は、non-volatileな変数へのアクセスと同じ
だから、この流れにvolatileは何の関係も無いよ

736:デフォルトの名無しさん
09/09/03 09:27:34
>>706
読み取り側ではメモリバリアはいらないの?


737:デフォルトの名無しさん
09/09/03 10:14:24
_Valueの値を読み込む前にその指す先の値を読み込むのは不可能だから
メモリバリアがなくても読み込み順序は入れ替わらないはずで要らない・・・んじゃないかなたぶん

738:デフォルトの名無しさん
09/09/03 15:09:34
>>737
>_Valueの値を読み込む前にその指す先の値を読み込むのは不可能だから
>メモリバリアがなくても読み込み順序は入れ替わらないはずで要らない
それが成り立たないアーキテクチャもあるんだな。
URLリンク(www.cs.umd.edu)

739:デフォルトの名無しさん
09/09/03 15:31:35
volatileの話をするときは、C/C++なのかJava/C#(CLI)なのかをはっきりさせろ。
それぞれのvolatileの意味はまるっきり別なんだからな。

740:デフォルトの名無しさん
09/09/03 15:59:30
そうか、やっぱりだめか
例の記事は今見直したらvolatileが付いてるな
なるほど

741:デフォルトの名無しさん
09/09/03 16:18:16
それはメモりバリアかvolatileどっちかって話だから意味ないよ


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