トップ «前の日記(2009-05-13) 最新 次の日記(2009-05-15)» 編集

かにの泡ぶく


2009-05-14 爽やかな朝。

_ 湿度31%。

今朝の我が部屋、開けた窓から爽やかな空気が気持ちよいです。9時現在、気温22度、湿度31%。

ここ数日、24時間連続稼動で重い計算させているWorkstationがあるせいで少し室温高めですが、実に気持ちよい朝です。

_ 日経反落・・・

少し大きく下げましたので、久しぶりに買い参戦してみました。

富士写、タムロン、IHI の3銘柄分散買い。

去年食らったダメージからまだ完全に回復できず、未だ運用資金は元本割れ状態ですが、あと少しでなんとか元本まで這い上がれそうです。

一時は評価額で元本の半分ぐらいにまで落ちましたからね〜。ようやくここまで持ち返してきました。

これだから株は面白いですね。

_ 備忘録:MultiThreadは難しい・・・

画像処理の高速化のために、いろんなところでコードのマルチスレッド化を行っているのですが、生成スレッドが全部終わったどうかを監視するために、以下のようなコードを書いてみました。Windows / Visual C++ です。

static int si_ThreadDoneCounter = 0;

static UINT doBeginThread1( LPVOID pParam ) // スレッド制御関数 { Do_SubEffect(); // 画像処理の分割処理を行う。 si_ThreadDoneCounter++; return 0; }
void CImageProc::DoEffect() { long loop; long divNum; // 画像処理分割処理数(= 総スレッド数)

・・・・・

si_ThreadDoneCounter = 0;
for (loop = 0; loop < divNum; loop++) { ::AfxBeginThread(doBeginThread1, (LPVOID)this); }
while (1) { if (divNum <= si_ThreadDoneCounter) { // si_ThreadDoneCounter値を見てスレッド終了待ちする break; } Sleep(1); } }

これがですね、うまく動かない場合がかなり頻繁にあるんですよ。いや〜、解析に随分嵌りました。

なんと! マルチコアのCPUでこのコードを動かすと、 si_ThreadDoneCounter++; を divNum 回通っても、divNum 回インクリメントされない場合があるのです。

どうしてこういう現象が発生するのかの根本原因は追究していないのですが、現象として確認できます。どうも、複数のCPUで偶然にも同時に si_ThreadDoneCounter++; が実行された場合、1 回分しかインクリメントされない・・・ということのように思える現象です。

マルチコアでマルチスレッドすると、これって普通に起きる現象なんでしょうかね?

う〜む難しい・・・


    2009年5月16日 15:00追記。

    多くのみなさんからツッコミ頂戴しまして感謝であります! 結局、WindowsのAPIで用意されているMutexロックを使って排他制御することで、期待する動作を得られるようになりました。

    具体的なコードはこんな感じ。

    static int si_ThreadDoneCounter = 0;
    
    static UINT doBeginThread1( LPVOID pParam ) // スレッド制御関数 { Do_SubEffect(); // 画像処理の分割処理を行う。
    hMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, k_MYMUTEX_NAME); dwRet = WaitForSingleObject(hMutex, k_ProcMutexTimeout);
    if (dwRet == WAIT_TIMEOUT) { DoTimeoutErrorHandler(); // Timeoutエラー処理 } else { si_ThreadDoneCounter++; }
    ReleaseMutex(hMutex);
    return 0; }
    void CImageProc::DoEffect() { long loop; long divNum; // 画像処理分割処理数(= 総スレッド数)

    ・・・・・

    hMutex = CreateMutex(NULL, FALSE, k_MYMUTEX_NAME); si_ThreadDoneCounter = 0;
    for (loop = 0; loop < divNum; loop++) { ::AfxBeginThread(doBeginThread1, (LPVOID)this); }
    while (1) { if (divNum <= si_ThreadDoneCounter) { // si_ThreadDoneCounter値を見てスレッド終了待ちする break; } Sleep(1); } CloseHandle(hMutex); }

_ 昨日の話について・・・

雇用契約の更新打ち切りについて昨日少し触れましたが、何通かメールでコメントをいただきました。ありがとうございます。

私も・・・あの話を書く時、『ひょっとして荒れるかな?』なんて少し怖かったのですがさすが 泡ぶく の読者のみなさん大人な方ばかりです。良き読者に恵まれて、本当によかったと思っております。

で、本題。

そうなんですよ。雇用を拡大するということと、雇用契約の更新打ち切りの話は全く別の問題であり、分けて考える必要があります。

私が昨日触れたのは、あくまで『契約の履行』という部分での話です。絶対的に働く口が少ない、正規従業員(細かいことなのですが私は 正社員 という言葉を所謂会社の従業員に対して使うことに抵抗がありますので、あえて 正規従業員 と書きます)の募集数が圧倒的に少ない・・・だから、派遣業態に頼らざるを得ないという事情もあるでしょう。それはそれで非常に大きな問題ですが、それと『合意した契約の運用』とは、全く別の問題です。

ここをごちゃまぜにしてしまうから、話がわかりにくくなり議論が錯綜してしまう。

雇用を拡大するためにはどうしたらよいのか、どうしてこんな風になってしまっているのか、なんでこうなったのか・・・

それはいろいろな要因要素がありますし、あまりにも壮大な問題でありますが、しかし、可能な限り、そのへんのことについても日頃から真剣に考えておく必要があると、思います。

個人で出来ることは極めて限られていますが、だからと言って「世間が悪い」「会社が悪い」「景気が悪い」「政治が悪い」と、外的要因のせいにばかりしていても、全く問題は解決しません。



現状が好ましくない・・・悪いと思うなら、どうすれば改善できるのか?
そのためには、自分には、何が出来るのか?


そして・・・


自分は現状において最善な結果を得るための努力をちゃんとしているのか?


を、常に考える必要があります。

楽して暮らせるほど、世の中そんなに甘くはありません。

しかし、真剣に生きようと思えば、生きることのできる世の中だと、私は思っています。

本日のツッコミ(全8件) [ツッコミを入れる]
_ yimamura (2009-05-14 14:05)

> 自分は現状において最善な結果を得るための努力をちゃんとしているのか? <br><br>耳が痛いです。<br>してないんですよ!少なくとも僕はしてない。<br>いかんなぁいかんなぁと思いつつ流される日々です。

_ 青木@管理人 (2009-05-14 16:25)

いやいや・・・そりゃ私だって、ああ言ってみたものの反省の毎日、日々是修行なりです・・・<br>でもいちお、志だけでもって思って、激しく自戒を込めて書いてみちゃいました。

_ うめ (2009-05-15 17:48)

マルチスレッドでstatic変数を使う場合、mutexとかを使ってロックする必要があったような気がします。

_ 青木@管理人 (2009-05-15 20:17)

mutexかぁ。昔unixで使ったことあるなぁそういえば。調べてみよう。Thanks-

_ simi (2009-05-16 08:43)

スレッドのコンテキストスイッチングはCPUがstatic変数をメモリから取ってきて書き込むまでの間にも起こるので、ロックは絶対必要ですよ。<br>セマフォとかで検索すればいろいろ出てくるかも。<br>シングルCPUシングルコアでも起こるはずです。マルチコアに比べて頻度は少なくなるかもですが。

_ 青木@管理人 (2009-05-16 09:33)

シングルCPUでも理論的には起こるのだと思うけど、現実的には起き得ないみたいよ。<br>スタックから変数を取り出してインクリメントして戻すという操作に何クロック使うか? を考えると、起き得ないように思う。<br>とはいえとりあえず昨晩mutexロックしたコードをひたすら走らせているのだけど、いまんところ調子いい感じ。

_ よっぱらい (2009-05-16 11:47)

内のプログラマーにみせたらこんな回答でした。<br><br>排他制御処理が誤っています。<br><br> while (1) {<br><br>この行 → if (divNum <= si_ThreadDoneCounter) {<br><br> // si_ThreadDoneCounter値を見てスレッド終了待ちする<br> break;<br> }<br> Sleep(1);<br> }<br><br>ここがスレッド終了を判断している部分なのですが、基本的にOSはスレッド終了監視をOSが提供するAPIで監視できますので、<br>その手法を使うべきでしょう。また仕方なくこの方法を使うにしても、si_ThreadDoneCounterを更新する部分は排他制御しないと<br>正しい数値が更新されません。また、コンパイラにより最適化された場合は、上記の行の部分は常に同じ値を参照することになり永久に終了しない可能性があります。si_ThreadDoneCounterの変数宣言を、下記のように修正すれば確実にsi_ThreadDoneCounterの値を参照できます。<br>static volatile int si_ThreadDoneCounter = 0;  ということでした。

_ 青木@管理人 (2009-05-16 14:53)

よっぱらいさん:わざわざありがとうございます。感謝!<br>結局現状は、OSのAPIでMutex Lockをかけることで無事問題なく動作できるようになりました。<br>このへんちゃんとやらないと、やっぱ駄目ですね。


もっと読みたい奇特なかたは、↓の読みたい月をクリックしてね。
2000|04|
2005|01|02|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|08|09|10|11|12|
2014|01|03|04|12|
2015|09|12|
2016|04|05|12|
2017|12|
2018|09|12|
2019|02|03|10|12|
2020|04|12|
2021|12|
2022|12|
2023|03|12|
2009年
5月
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31


最新ツッコミ

  1. 青木@管理人 (10-09)
  2. こいち (10-09)
  3. 万年初心者 (04-01)
  4. 青木@管理人 (03-31)
  5. 万年初心者 (03-31)



  • 12月31日
    永劫回帰?!
  • 03月14日
    ランチに超高級カップ麺を食す。
  • 12月31日
    無為自然。
  • 12月31日
    今年もあと少し・・・
  • 12月31日
    大晦日。
  • 04月29日
    PCR検査陽性者数っていつの陽性者数?
    • 1. 日々の陽性者数はほぼほぼ意味無い。
  • 04月23日
    コロナ禍に思うこと。
    • 1. よんどころない話です。軽く読み飛ばしてください。
  • 04月22日
    買うとおカネが貰える?!
    • 1. 原油の価格がマイナスってナニソレ?!
  • 04月20日
    コロナ禍に思うこと。
    • 1. せめてもの報い。
  • 12月31日
    生きるということ。