- 1 名前:デフォルトの名無しさん mailto:sage [2005/11/03(木) 11:23:05 ]
- マルチスレッドプログラミングについて語るスレ。
OS・言語・環境は問わないが、それゆえ明記すべし。 その1 pc3.2ch.net/test/read.cgi/tech/997345868/ その2 pc5.2ch.net/test/read.cgi/tech/1037636153/ その3 pc8.2ch.net/test/read.cgi/tech/1098268137/
- 862 名前:デフォルトの名無しさん mailto:sage [2006/08/10(木) 09:39:08 ]
- >>858
GUIのエディタだと、 ウィンドウサイズ変えられるのに対応したり、 マウスで指定された範囲を反転表示したり。
- 863 名前:デフォルトの名無しさん mailto:sage [2006/08/10(木) 10:35:09 ]
- しながら同時にテキスト入力できるのか!
- 864 名前:デフォルトの名無しさん mailto:sage [2006/08/10(木) 10:39:46 ]
- >>858
画面出力とか。
- 865 名前:デフォルトの名無しさん [2006/08/11(金) 22:57:19 ]
- どこまでがマジレスなのか…
- 866 名前:デフォルトの名無しさん [2006/08/14(月) 21:40:21 ]
- みんなスレッドプールって最大数超えた場合どうしてる?
- 867 名前:デフォルトの名無しさん mailto:sage [2006/08/16(水) 01:06:17 ]
- 再起動
- 868 名前:デフォルトの名無しさん mailto:sage [2006/08/16(水) 08:42:10 ]
- 海に行く
- 869 名前:デフォルトの名無しさん mailto:sage [2006/08/16(水) 18:56:59 ]
- オレは泳がないから
- 870 名前:デフォルトの名無しさん mailto:sage [2006/08/18(金) 00:26:11 ]
- 眺めてるだけでも心和むじゃまいか
- 871 名前:デフォルトの名無しさん mailto:sage [2006/08/18(金) 07:41:37 ]
- 潜りてー
あの不要な音が聞こえない感覚が良いんじゃー
- 872 名前:デフォルトの名無しさん [2006/08/18(金) 14:51:42 ]
- >>866
@IT:連載:.NETマルチスレッド・プログラミング入門 第4回 www.atmarkit.co.jp/fdotnet/mthread/mthread04/mthread04_01.html - 53k - キャッシュ - 関連ページ スレッドプールのカスタマイズ www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=27266&forum=12&3 - 26k - キャッシュ - 関連ページ [ 他、www.atmarkit.co.jp内のページ ] スレッドプール 最大数 の検索結果 約 1,440 件中 1 - 50 件目 (0.59 秒)
- 873 名前:デフォルトの名無しさん mailto:sage [2006/08/18(金) 19:28:16 ]
- 大阪には株式会社モータープールがあり、東京には株式会社月極がある。
- 874 名前:デフォルトの名無しさん mailto:sage [2006/08/26(土) 09:06:17 ]
- MFCでマルチスレッドのプログラムを作成していますが、引数の受け渡しのところで悩んでいます
struct ThreadParams{ int a; int b; int c; }; BOOL MyApplicationDlg::OnInitDialog() { … struct ThreadParams tParams; tParams.a = 1; tParams.b = 2; tParams.c = 3; AfxBeginThread(MyThread, (LPVOID)&tParams, THREAD_PRIORITY_NORMAL); return TRUE; } UINT MyApplicationDlg::MyThread(void * param) { struct ThreadParams tParams = (struct ThreadParams)(*param); ←ここで既に呼び出し元のtParamsが消えているかも? /* tParamsを使っていろいろ処理 */ return 0; } 上のようなコードを書いたのですが、OnInitDialog中のtParams変数のスコープは関数内だけなので MyThread関数でtParamsを受け取ろうとしたときには既に消えている可能性があるのではないかと思いました。 こういう場合には呼び出し元で new してスレッドの方で delete するとかで対処するのでしょうか? 他に何かよい方法があればアドバイスをお願いします。
- 875 名前:デフォルトの名無しさん mailto:sage [2006/08/26(土) 09:33:15 ]
- MyThread()とダイアログクラスの結びつきが強いのなら、クラスメンバにしておけばいいんでない?
要は、スレッドよりも長寿命ならいいわけだから。 #ダイアログクラスよりもスレッドの方が長寿ならこの手は使えないのは当然だけど。
- 876 名前:874 mailto:sage [2006/08/26(土) 10:20:36 ]
- そうですね。ぐぐって探してみましたがクラスメンバにしているサンプルがありました
とりあえずこの方法でやってみます。ありがとうございました
- 877 名前:デフォルトの名無しさん mailto:sage [2006/08/26(土) 10:26:12 ]
- >>874
あんたの心配は正しい。 領域を渡して後はスレッド側でよろしことする以外にも... ・スレッド側で (コピーしておくとして) そのパラメータを 使わなくなるまで親を待たせる。 ・領域を静的に確保する。 ・スレッドが起動してからパイプとかでパラメータをもらう。 等等。個人的には new / delete を使うことが多い。
- 878 名前:デフォルトの名無しさん mailto:sage [2006/08/26(土) 19:08:33 ]
- volatileですべて解決します。
グローバル変数にvolatile属性を付けて置く。 これ最強。
- 879 名前:デフォルトの名無しさん mailto:sage [2006/08/26(土) 19:17:49 ]
- >>878
>>877 >・領域を静的に確保する。
- 880 名前:デフォルトの名無しさん mailto:sage [2006/08/26(土) 20:26:54 ]
- 何でvolatileネタって流行ってるの?
とくに引っ張って面白いネタとも思えないけど
- 881 名前:デフォルトの名無しさん mailto:sage [2006/08/26(土) 21:25:02 ]
- sizeof(int)以下ならvolatileでいいですよね?
排他は重いからやりたくないんですが・・・ という馬鹿が一時期沸いた
- 882 名前:デフォルトの名無しさん mailto:sage [2006/08/26(土) 21:28:54 ]
- すごいな
全く意味のわからん質問だ
- 883 名前:デフォルトの名無しさん mailto:sage [2006/08/27(日) 16:59:50 ]
- マルチスレッドなんか使わなければ解決
- 884 名前:デフォルトの名無しさん mailto:sage [2006/08/27(日) 19:58:38 ]
- >>877
スレッドを越えてのnew / deleteは止めとけ。 つーか、調べると分かるが、状況によって手痛いしっぺ返しを喰らうぞ。
- 885 名前:デフォルトの名無しさん mailto:sage [2006/08/27(日) 21:05:30 ]
- アホ発見 >>884
状況を具体的に説明してみろよ
- 886 名前:デフォルトの名無しさん mailto:sage [2006/08/27(日) 21:34:42 ]
- >>884
それは874に宛てるべき内容だ。 呼ぶ側がdeleteするか、呼ばれた側がdeleteするかは統一するべきだとは思う。 呼ばれた側がdeleteする場合は、浅いコピーをして使い回す場合に対応できないからオススメできない。
- 887 名前:デフォルトの名無しさん mailto:sage [2006/08/27(日) 23:06:55 ]
- >>886
> 呼ばれた側がdeleteする場合は、浅いコピーをして使い回す場合に > 対応できないからオススメできない。 kwsk
- 888 名前:デフォルトの名無しさん mailto:sage [2006/08/28(月) 00:21:30 ]
- シャローコピーで参照を共用してる場合
データレースが起きるよヤバイよって事じゃないの? そんなもん別スレッドに渡すなよと思うけど
- 889 名前:888 mailto:sage [2006/08/28(月) 00:23:33 ]
- なんか違うな
忘れてくれ
- 890 名前:デフォルトの名無しさん mailto:sage [2006/08/28(月) 00:41:46 ]
- しったかぶりっこ
- 891 名前:デフォルトの名無しさん mailto:sage [2006/08/28(月) 01:49:18 ]
- 参照ってもスレッドに渡す前に参照カウント1アゲるだろ
- 892 名前:デフォルトの名無しさん mailto:sage [2006/08/28(月) 01:50:45 ]
- ぶるぶるぶりっこ
- 893 名前:デフォルトの名無しさん mailto:sage [2006/08/28(月) 02:58:49 ]
- 一体何の話をしてるのだろう?
- 894 名前:デフォルトの名無しさん mailto:sage [2006/08/28(月) 05:08:03 ]
- ぶりっ子ロックンロール / 紅麗威甦
- 895 名前:デフォルトの名無しさん mailto:sage [2006/08/28(月) 20:39:11 ]
- 環境はWindowsです。
メインスレッドで生成されたWindowから、別スレッドを起動します。 このスレッドは、ファイルを1行づつ読み、 vector<string>に50件溜まったら、Windowへ通知します。 とりあえず下のような感じで組んだのですが、 Windowsが閉じられた場合、このスレッドを破棄しないといけません。 もしスレッドを破棄したらNetFileReaderのオブジェクトって、 解放されないのですよね。 こういうプログラムって、どうやって組むのが良いでしょう? static vector<string> text; void NetwordThread::execute(void* pData) { MyWindow* win = (MyWindow*)pData; NetFileReader* reader = new NetFileReader("hoge.txt"); string* line; while ((line = reader->readLine()) != NULL) { text.push_back(*line); if (text.size() > 50) { SendMessage(win->m_hWnd, WM_MY_MESSAGE, NULL, (LPARAM)&text); text.clear(); Sleep(10); } SendMessage(win->m_hWnd, WM_MY_MESSAGE, NULL, (LPARAM)&text); text.clear(); _endthread(); }
- 896 名前:デフォルトの名無しさん mailto:sage [2006/08/28(月) 21:25:26 ]
- 中断フラグを作って、メイン側で Window を閉じる時に
フラグを On にする。 スレッド側は中断フラグを一行毎にチェックしてて、 On になったら、速やかに終了する。 通常のディスクファイル相手ならこれでいいと思う。 ネットワークファイルとかで一行の読み出しにすごく時 間がかかる場合があるならその読み出し処理自体を中断 する必要があると思う。
- 897 名前:デフォルトの名無しさん mailto:sage [2006/08/28(月) 21:52:15 ]
- ていうか、「Windowが閉じられたら」とか「スレッドを破棄」とか書いてるけど
普通は、閉じるボタンが押されたら、フラグなりイベントなりでスレッドに対して終了を通知して ワーカースレッドは自分で後始末をしてから終了する、 GUIスレッドはワーカースレッドが終了するまで待機する っていうふうに作るのが普通だろ。
- 898 名前:895 mailto:sage [2006/08/28(月) 21:54:13 ]
- どもです。
中断フラグをONするメソッド作って、中はMutexで排他処理、 スレッドのexecute()の方はSendMessage()をMutexで排他処理 しておけば、1行ごとにチェックまではしなくてよいかな? あと、スレッドの中でSleep()呼ばないと、このスレッドに完全に制御が移ってしまい、 スレッドが終了するまでWindowが固まってしまいます。 これはそういうもんでしょうか? マルチスレッドって、どこで処理が割り込むかわからないものだと思っていたのですが。
- 899 名前:895 mailto:sage [2006/08/28(月) 21:55:29 ]
- >>897
書き込み中にレスが。 ええ、その「普通はこうだ」ってのが聞きたかったんです。 なにぶん素人なのもので・・・
- 900 名前:デフォルトの名無しさん mailto:sage [2006/08/28(月) 22:05:09 ]
- 固まらなねーよ。
プライオリティとかいじってなきゃな。
- 901 名前:895 mailto:sage [2006/08/28(月) 22:25:55 ]
- _beginthread()呼んでるだけで、プライオリティはいじってないですね。
ActiveX内で、やってるからかなぁ。
- 902 名前:デフォルトの名無しさん mailto:sage [2006/08/28(月) 23:06:40 ]
- >>895
>解放されないのですよね。 そもそも、なんで new で割り当ててんの?
- 903 名前:デフォルトの名無しさん mailto:sage [2006/08/29(火) 04:29:53 ]
- >>898
> あと、スレッドの中でSleep()呼ばないと、このスレッドに完全に制御が移ってしまい、 > スレッドが終了するまでWindowが固まってしまいます。 SendMessage()のせいじゃね?
- 904 名前:895 mailto:sage [2006/08/29(火) 14:19:52 ]
- >>903
その通りでした。SendMessageは使わない方がよさそうですね。 スレッドがデータ格納するバッファは、Window側でタイマーで定期的に監視。 スレッドがバッファに格納するときと、Windowがバッファから取得するときは、 mutexで排他処理かましておくと良いかな。
- 905 名前:デフォルトの名無しさん mailto:sage [2006/08/29(火) 16:46:22 ]
- PostMessage()使ってみたら?
- 906 名前:デフォルトの名無しさん mailto:sage [2006/08/29(火) 20:26:56 ]
- タイマーで監視しなくても、PostMessage()で合図送ればいんじゃね?
- 907 名前:895 mailto:sage [2006/08/29(火) 21:41:10 ]
- PostMessageだと、ちょっと不安があってやめたんです。
たとえば、スレッドからPostMessageを呼んだ直後に、 Windowのスレッドがアクティブになって、Windowを閉じる処理をした場合、 Windowのハンドルが無効になった後に、メッセージを飛んできて、 死亡したりしませんかね?
- 908 名前:デフォルトの名無しさん mailto:sage [2006/08/29(火) 21:42:23 ]
- 誰が死亡するの?
- 909 名前:895 mailto:sage [2006/08/29(火) 21:50:03 ]
- オサーンのプログラム。無効なウィンドウハンドルに投げようとして
ハングしたりしないかなと。
- 910 名前:デフォルトの名無しさん mailto:sage [2006/08/29(火) 21:51:47 ]
- ,、‐ " ̄:::゙:丶、
,r::::l3゙::::::::/ハヽ:ヽ::::、:ヽ {::://:::::::// ヽ\ト、:::::::! ヾ l:::::::/ 丶 `ヾ ィ、:::| |;:r::| O` 'O ゙ハ| < ないない ヽハ :.:. :.: レ ´\ r‐--‐、,ノ r、 r、/ヾ ̄下ヘ ヽヾ 三 |:l1、_ヽ/__ .ィヽ \>ヽ/ |` } n_n| | ヘ lノ `'ソ l゚ω゚| | /´ /  ̄|. | \. ィ ___ | | | ノ l | | | | i:| |
- 911 名前:デフォルトの名無しさん mailto:sage [2006/08/29(火) 22:29:31 ]
- >>907
> メッセージを飛んできて、 > 死亡したりしませんかね? メッセージを割り込みみたいなもんと勘違いしてないか?
- 912 名前:895 mailto:sage [2006/08/29(火) 22:58:03 ]
- いや、それはないです。
PostMessageも当然、中でいろいろやってますよね。 PostMessageで実際にキューにメッセージ入れる直前に、 Windowのスレッドに切り替わることってないんですかね?
- 913 名前:デフォルトの名無しさん mailto:sage [2006/08/29(火) 23:09:22 ]
- そろそろスレ違い
- 914 名前:デフォルトの名無しさん mailto:sage [2006/08/30(水) 00:04:27 ]
- >>909
無効なハンドル次第では、デスクトップの再描画とか起こるかも。
- 915 名前:デフォルトの名無しさん mailto:sage [2006/08/30(水) 00:26:29 ]
- >>914
909じゃないけど詳しく教えてください
- 916 名前:デフォルトの名無しさん mailto:sage [2006/09/05(火) 22:30:07 ]
- そりゃロックしたままSendMessageしたらデッドロックだろうよ
- 917 名前:デフォルトの名無しさん [2006/09/06(水) 21:28:12 ]
- 居なくなった人のプログラムを押し付けられたんだけど、
CreateThread()した後、即CloseHandle()している。 どうして即CloseHandle()するのか、 Thread関数内のExitThread()直前に呼べばいいんじゃないのか、 そもそもCloseHandle()しなくてもExitThread()するんだから要らないんじゃないのか と思うんですが、誰も(??) そのままにしておけばいいんでしょうか。
- 918 名前:デフォルトの名無しさん mailto:sage [2006/09/06(水) 21:53:38 ]
- >>917
MSDN の CreateThread あたりに理由は書いてあると思ったけど、 調べてみた? 推測はほどほどにして、ちゃんと確認したほうがいいよ。
- 919 名前:デフォルトの名無しさん mailto:sage [2006/09/07(木) 01:04:39 ]
- >>917
> Thread関数内のExitThread()直前に呼べばいいんじゃないのか、 ハンドルの話じゃないけど… マルチスレッドプログラミングにおいて、「〜の直前だから大丈夫」 なんてこと考えてたらはまるよ。
- 920 名前:デフォルトの名無しさん mailto:sage [2006/09/07(木) 13:24:51 ]
- >>917
CreateThread - ExitThread - CloseHandleするのがここでのならわし。 盲目的にこうしてればいいよ。
- 921 名前:デフォルトの名無しさん mailto:sage [2006/09/07(木) 15:03:17 ]
- ぉぃぉぃ
- 922 名前:デフォルトの名無しさん mailto:sage [2006/09/08(金) 00:47:23 ]
- いやmmapしないとダメ
- 923 名前:デフォルトの名無しさん [2006/09/08(金) 12:38:24 ]
- ロックしないでグローバル変数に(intなど機械語1命令で読み書き可能な
サイズという条件で)アクセスするケースを考えます。 int a; void thread1(){ while(1)a=0x0000ffff; } void thread2(){ while(1)a=0xffff0000; } void thread3(){ while(1)printf("%08x\n",a); } このとき、thread3で0x0000ffffか0xffff0000以外の数字が 表示される可能性はありますか?
- 924 名前:923 mailto:sage [2006/09/08(金) 12:40:49 ]
- 補足ですが、シングルプロセッサとマルチプロセッサ両方の
ケースでどうなのか知りたいです。環境はWindows2000以降の x86アーキテクチャを想定しています。
- 925 名前:デフォルトの名無しさん mailto:sage [2006/09/08(金) 13:17:47 ]
- aの初期値が延々と表示される可能性すらあるな
- 926 名前:デフォルトの名無しさん mailto:sage [2006/09/08(金) 22:28:47 ]
- volatile厨臭いな
釣りか? 釣られたのか?
- 927 名前:デフォルトの名無しさん mailto:sage [2006/09/08(金) 23:08:48 ]
- >>923
メモリーバスが CPU のバストランザクションをソフトの都合に会わせて 実行する保証はどこにもないんだから バスサイズ 8 bit のシステムで 1 on cpu0 2 on cpu1 3 on cpu2 ってシチュエーション考えれば何でもありじゃん
- 928 名前:デフォルトの名無しさん mailto:sage [2006/09/08(金) 23:34:45 ]
- あっそう
- 929 名前:923 mailto:sage [2006/09/09(土) 02:25:04 ]
- >>925>>926
すみません。初期値の部分は、 volatile int a = 0xffff0000; とさせてください。後付申し訳ないです。この辺はあまり捻らないで(^^;) >>927 >ってシチュエーション考えれば何でもありじゃん 実際問題として、Windowsのマルチプロセッサ環境で失敗する 例を容易に確認できますでしょうか? ハード環境を簡単に 用意するわけにも行かないので、いろんな人が見ているここに 尋ねてみました。 シングルプロセッサでは失敗するケースはこれまでの経験上無い ものと思われますが…(こちらは失敗するケースを見たことないです)
- 930 名前:デフォルトの名無しさん mailto:sage [2006/09/09(土) 04:21:21 ]
- 前スレでまったく同じ議論があったよ
保証されるかどうかはアーキテクチャに強く依存する それこそIntelとAMD、Intel内でもその世代により異なる >シングルプロセッサ マルチコア時代にそういう括りはやめたがいい HTもキャッシュ絡みでerattaがあった ひとつ聞いとこう、趣味?仕事?
- 931 名前:デフォルトの名無しさん mailto:sage [2006/09/09(土) 05:04:16 ]
- 386SX以外の32bitx86は
メモリバス(システムバスでもHTバスでも)は32bit同時に読み書きするだろ。 キャッシュが反映されないとか関係ない。 全部(全bit)書き込まれるか、全部書き込まれないかどちらか。
- 932 名前:デフォルトの名無しさん mailto:sage [2006/09/09(土) 05:06:02 ]
- あ、ちゃんとアラインされている場合の話ね。
- 933 名前:仕様書無しさん mailto:sage [2006/09/09(土) 08:41:48 ]
- >931-932
マルチプロセッサ環境で、あるCPUが内部キャッシュ内に保持しているDWORD 値の一部バイトを書き換えて、ライトバックする前に、ほかのCPUがDWORDの 一部バイトを書き換えるという状態になったらどう動作すんの?
- 934 名前:923 mailto:sage [2006/09/09(土) 09:07:35 ]
- >>932
Interlock系のAPIがマルチプロセッサ環境では32bitアラインを要求しますね。 関連があるのでしょうかね? >>933 こちらへのレスではありませんが、おっしゃるケース (一部書き換え)は考えてません。問題にしたいのは 全ビット書き換えた時読み出し時に一部しか書き変わ っていない状況があるかどうか、なので。 ちょっと動作検証と、ロック有り無しの場合で性能的に どれほど差が出るのかプログラムを作って試してみたいと思います。
- 935 名前:デフォルトの名無しさん [2006/09/09(土) 09:21:18 ]
- volatile最強!!!
- 936 名前:デフォルトの名無しさん mailto:sage [2006/09/09(土) 09:41:14 ]
- Interlockとか_MemoryBarrier使わない必要性あるの?
速度が必要ならアルゴリズムとか排他制御の範囲とか無待機アルゴリズムとか から高速化できないの? スレッドの優先順位とか、他のプロセスの稼動状況とかでも状況変わるから 動作検証を完全にやることは無理でしょ。 CPUやMBの仕様書をNDA結んで手に入れて調べるぐらいしないと。
- 937 名前:デフォルトの名無しさん mailto:sage [2006/09/09(土) 09:45:06 ]
- >>933
それは「起こらない」でしょ。 なぜならば、キャッシュ間のコヒーレンシを保つための仕組みを持っているのが マルチプロセッサシステムだから。
- 938 名前:デフォルトの名無しさん mailto:sage [2006/09/09(土) 09:51:15 ]
- >>934
特定少数の chip setに限定するとかなら話は別だろうけど, C コンパイラが LOCK prefix つけて load/store するコードを 吐き出すわけではないし, ハードウェアの作り次第だと思われ...
- 939 名前:デフォルトの名無しさん mailto:sage [2006/09/09(土) 09:53:31 ]
- >>937の仕組みが外部バス接続のために遅くなり、糞CPUと呼ばれたのがPenD。
- 940 名前:デフォルトの名無しさん [2006/09/09(土) 10:30:49 ]
- ついにvolatileの最強さが証明されるわけだ
>>811 おめでとう
- 941 名前:デフォルトの名無しさん mailto:sage [2006/09/09(土) 12:02:27 ]
- >>937
何が「起こらない」っと言ってるのか...。
- 942 名前:923 mailto:sage [2006/09/09(土) 12:45:41 ]
- >>936>>938
ロックしないと明らかにまずい状況はもちろんロックしますが、 単純な場合はロック無しでできたらいいという場面もありそうです。 皆さん、スレッド間で共有されるグローバル変数全て、万一の場合に 備えてくまなくロック系API使ってアクセスしてますか? 「書いて」「読んで」その状況において不都合がない場合は、 API通さずに普通のCの文法で書ければ言うことはないじゃないですか。 スレッド系の解説してる本にも、単純なカウンターとかロック系の API無しでアクセスしてます。ここで問題にしているのはそういう ごく単純なプリミティブなアクセスの話です。 NDAや「ハードウェアの作り次第」とか、そういう話まで持ち出されるのは 個人や小さい事業所でどうこうするのは不可能ですし、現実的なアクション とは到底言えないと思います。 要は世に出回っている大抵のWindowsマシンでおかしくならない線を 探せばいいのだと思います。パッケージには全てのマシンで動作保障 するものではありませんとか書いてるソフトもありますし、試せる 範囲でおかしくならなければ(試して失敗が一つも無ければ)、 完全な厳密性までは得られなくても、こちらのスタンスとしてはOKです。
- 943 名前:923 mailto:sage [2006/09/09(土) 12:46:30 ]
-
厳密性を完璧にするなら世の中のマシン全部で試さないといけない じゃないという話にもなりますし、それはやはり現実味の無い話と しては上に書いてあることと大差ありません。理論にも実装にも ミスが無くてもおかしくなる環境は必ずあります。 一応持ってるマシンで検証プログラムを走らせましたがエラーする ケースは一度も起きませんでした。 性能に関しては、ロック無しを1とした場合、Interlocked系で読み書き すると5倍、CriticalSectionで排他すると200倍近い速度低下が起きます。 (テストプログラムは極端な例でしょう) 実際の使用状況は置いておき、5倍の負荷は精神的に嫌な感じです。 この辺気にしない人もいるでしょうが、気にしない人は他の場合でも 気にしないでしょうし、積み重なるともっさりしたソフトが出来そう なので、検証不可能な厳密性よりもこういうほうに労力や気を払いた いですね。 一応ソース貼っときますので、もし失敗例が実際に観測された人が居たら 教えてください。Windowsシステム上で一つでも反例があれば納得せざる を得ません。逆にある程度のサンプルで試して一度もエラーが無ければ それはOKというのが世の中というものでしょう。
- 944 名前:923 mailto:sage [2006/09/09(土) 12:50:44 ]
- #include "stdafx.h"
#include "windows.h" #include "winbase.h" #include "process.h" #include "mmsystem.h" #pragma comment(lib, "winmm.lib") #if 1 //ロック無し #define set_a(n) a = n #define get_a(v) v = a #elif 0 //Interlocked系で読み書き #define set_a(n) InterlockedExchange((long*)&a,n) #define get_a(v) v = InterlockedExchangeAdd((long*)&a,0) #else //CRITICAL_SECTION排他 #define _CS CRITICAL_SECTION cs; #define set_a(n) {EnterCriticalSection(&cs); a=n; LeaveCriticalSection(&cs);} #define get_a(v) {EnterCriticalSection(&cs); v=a; LeaveCriticalSection(&cs);} #endif 続く
- 945 名前:923 mailto:sage [2006/09/09(土) 12:51:29 ]
- volatile int a = 0x00001111;
volatile int t1_ct,t2_ct; void __cdecl thread1(void *param){ while(1){ set_a(0x00001111); t1_ct++; } } void __cdecl thread2(void *param){ while(1){ set_a(0x22220000); t2_ct++; } } 続く
- 946 名前:923 mailto:sage [2006/09/09(土) 12:52:50 ]
- int main(int argc, char* argv[])
{ #ifdef _CS InitializeCriticalSection(&cs); #endif unsigned int id1; HANDLE h1 = (HANDLE)_beginthread(thread1, 0, &id1); unsigned int id2; HANDLE h2 = (HANDLE)_beginthread(thread2, 0, &id2); #if 0 while(1)printf("%08x\n",a); #else printf("実行中……\n"); int loop = 0; int false_ct = 0; DWORD time = timeGetTime(); while(loop++ < 100000000){ int t; get_a(t); if(t != 0x00001111 && t != 0x22220000) printf("不整合発見(%d):%08x\n",++false_ct,t); if((loop & 0x7fffff) == 0) printf("loop:%d……\n",loop); } 続く
- 947 名前:923 mailto:sage [2006/09/09(土) 12:53:28 ]
- time = timeGetTime() - time;
TerminateThread(h1,0); TerminateThread(h2,0); printf("ループ%d回、失敗%d回、実行時間%.3f秒\n",loop-1,false_ct,(double)time / 1000); printf("スレッド1実行回数%d回\n",t1_ct); printf("スレッド2実行回数%d回\n",t2_ct); #ifdef _CS DeleteCriticalSection(&cs); #endif #endif return 0; }
- 948 名前:デフォルトの名無しさん mailto:sage [2006/09/09(土) 12:55:06 ]
- どうせなら、レスの最後を
/* 続く として、次のレスの頭を >xxxから */ とでもしてくれたらコピペの(後処理の)手間が減るのだが。
- 949 名前:923 mailto:sage [2006/09/09(土) 12:58:46 ]
- 済みません。あと、TerminateThreadしてるのはご愛嬌ということで。
- 950 名前:デフォルトの名無しさん mailto:sage [2006/09/09(土) 13:31:06 ]
- >>943
> 一応持ってるマシンで検証プログラムを走らせましたがエラーする > ケースは一度も起きませんでした。 じゃ、あなた的には、それでいいんじゃないでしょうか? > 実際の使用状況は置いておき、5倍の負荷は精神的に嫌な感じです。 > この辺気にしない人もいるでしょうが、気にしない人は他の場合でも > 気にしないでしょうし、積み重なるともっさりしたソフトが出来そう > なので、検証不可能な厳密性よりもこういうほうに労力や気を払いた > いですね。 「いかにして、ロックするべき部分を局所化して、ロックコンディションの テストする回数を減らすか」 を考えるべきであって、 「ここで動くんだから大丈夫じゃないか、きっとよそでも動く!」 ってな発想はしてはならないと思いますけど。 じっさいに、4CPU程度のマシンで動いていたけど、16CPU程度の NUMA アーキテクチャのターゲットマシンの持っていった場合、動作しなかった って前例は何度もみてます。
- 951 名前:923 mailto:sage [2006/09/09(土) 13:50:37 ]
- >>950
ソースを出してるので、失敗した出力を貼って いただけないでしょうか? 動作させた環境も 出来たらお願いします。
- 952 名前:デフォルトの名無しさん mailto:sage [2006/09/09(土) 13:52:15 ]
- もちろん、手持ちのマシンで動けば問題ないし、
たまにクラッシュしてもビジネス上問題ないならそれでいいんじゃ? 950も言ってるが、スレッドで共有する情報の塊に対してロックをかけるべきであって、 1足すとか状態を読んでそれに対する処理を行いさらに書くことはできないと思っておいたほうがいい。 それとソースだが、何でintrinsic命令使わないの?関数呼び出しコスト余計にかかってるよ。 printfのコストが多すぎだと思うが、計測間違ってない? あと、そこまで考えるならtimeGetTimeはつかえないでしょ。 精度の設定もしてないし、明らかに少しかじった初心者がやりそうなソースだ。
- 953 名前:デフォルトの名無しさん mailto:sage [2006/09/09(土) 14:02:55 ]
- だからホビーなんじゃないの?と
- 954 名前:923 mailto:sage [2006/09/09(土) 14:05:31 ]
- >>952
>1足すとか状態を読んでそれに対する処理を行いさらに書くことはできないと思っておいたほうがいい。 もちろんです。 >printfのコストが多すぎだと思うが ? 全て成功するケースでは、1億回のうちprintfは11回だけです。 無視しても問題ないと思いますが。 (途中経過のprintfが無しでも、ストップウオッチ計測で 十分優位な差が得られるほど負荷が変化するのはわかりますし、 なんなら途中経過のprintfは取ってください) 計測ループの中ではロック系のAPI以外の呼び出しは上記の 途中経過表示の微々たるprintf以外無いですよ。 >timeGetTimeはつかえないでしょ。 動作が秒単位に対してtimeGetTimeは10msオーダーです。 精度としては十分じゃないのですか? もし不足だと感じたら、 パフォーマンスカウンターでも使って書きなおしてください。
- 955 名前:923 mailto:sage [2006/09/09(土) 14:07:51 ]
- 補足、
>十分優位な差が得られるほど負荷が変化する ロックするしないを切り替えたときの負荷の変化です。
- 956 名前:923 mailto:sage [2006/09/09(土) 14:13:30 ]
- 後、今回の趣旨は、読み出し失敗があるかどうかなので、
そちらに関してお話ください。 レスを見ていると相当な環境の方もいるようですし、 ロック無しでの書き込みや読み出しがそれほど使用に 耐えないほどの不具合があるものなら、簡単に失敗の ケースが出ると思います。 失敗した状況が貼られれば何より説得力がありますので、 よろしくお願い致します。
- 957 名前:923 mailto:sage [2006/09/09(土) 14:15:05 ]
- あと、失敗しない限り発言しないでください。
失敗しなければ問題ありませんので。
- 958 名前:デフォルトの名無しさん mailto:sage [2006/09/09(土) 14:19:42 ]
- >>942
> 要は世に出回っている大抵のWindowsマシンでおかしくならない線を > 探せばいいのだと思います。 最近の風潮か? 製品事故が多くなった理由が垣間見えるようだ...。 >>943 > 理論にも実装にもミスが無くてもおかしくなる環境は必ずあります。 技術屋として見過ごせないんだけど、「ある」と言い切れる理由は? >>957 > あと、失敗しない限り発言しないでください。 ここは、お前の検証スレじゃない。 そういう発言したいなら、自前の掲示板でも作れ。
- 959 名前:デフォルトの名無しさん mailto:sage [2006/09/09(土) 14:23:05 ]
- intrinsicはスルーか。ソースまともに読むわけ無いだろ金ももらってないのに。
失敗する環境探したいなら、自分でマシン買ってやってろ。
- 960 名前:923 mailto:sage [2006/09/09(土) 14:27:21 ]
- >>958
>製品事故が多くなった理由が垣間見えるようだ...。 どうもすみません(^^;) >技術屋として見過ごせないんだけど、「ある」と言い切れる理由は? 話がそれたかもしれません。済みません。ユーザー環境の 不具合などです。完全な検証が出来ない以上、分る範囲で 調べることしか出来ないと思うので、完全完全を言われると 身動き取れなくなってしまうといいたかったのです。 後、>>957は悪戯じゃないですか?
- 961 名前:デフォルトの名無しさん mailto:sage [2006/09/09(土) 14:30:24 ]
- >>923
うぜえ、消えろ('A`)
- 962 名前:デフォルトの名無しさん mailto:sage [2006/09/09(土) 15:23:18 ]
- >>960
> ユーザー環境の不具合などです。 そのユーザー環境に「理論か実装」の不具合があるんでしょ。 「全ての環境で試験なんかやってられねー」と言うのは当然至極なんだけど、 理論的な裏づけもなく1万回やったから大丈夫と言うのはちょっと違う気が する。 もちろん現実的には取りきれないバグをタイミングとかで逃げて1万回テス トしたから多分大丈夫だよねーと言って出すケースはないわけじゃないけど、 技術屋としてはもやもやが残ってる。 そもそもこの話は「検証不可能な厳密性」じゃないよ。いくつもの論文があ るし、このスレでも議論されてる。 (まともな意見のみを取り出すのは難しい が) > 後、>>957は悪戯じゃないですか? いたずらなら、2行目は >>957 へのレスだ。 でも、いたずらかどうかにかかわらず1行目はあんたへのレスだよ。
|

|