昔の最近の出来事(2012.02)

2012/02/29

気持ち早めに帰着。

ちょろり調べ事。

2012/02/28

早くも無く遅くも無く。

POV-Rayの 3.7 RC4が来ていたり。 RC3から1年以上経ってたりするのですが、まだRCというステータスな模様。 リリースされない理由は何なのかしら?

少し使ってみたのですが、テクスチャファイルをみつけられなくてエラー。 RC3以前だと特に問題無くレンダリングできたので、指定の方法が変わった のか何かしらバグっているのか。

あまり読まずに積んであった「BINARY HACKS」というオライリー本。 80bit浮動小数点の件で少し文書があったので読み直していたところ、 セキュアプログラミングの章でValgrindと いうツールの存在を知ったり。メモリリークなどを検出できるという 自動検査ツールという感じ。残念ながらWindows向けの公式な移植は 無い模様。Fedoraでは使えたので、gdcでコンパイルしたバイナリをvalgrind に食わせてみた所、phobos内のあちこちに何やら色々怪しげな点がありそうな 旨のメッセージが出たり。エラーの見方とかがイマイチよく判らないのが ヘボなのですが、これ、うまく使えないかなぁ?と思ったり。

2012/02/27

早くも無く遅くも無く。

ちょろっと調べ事をして終了。

2012/02/26

昼ごろ起床。

昨日の深夜にやってた作業のまとめ。

gdcのsetupスクリプトを実行する時に、 Mercurial SCMのhgコマンドが 使えるならば、RevisionやIDをワークセットから取得して、バージョン表示に組み込む 仕掛けが入ってます。 TANEの使っているMinGW環境ではhgコマンドが使えなかった訳ですが、 それを使えるようにしてみたり。

基本的にはこのページ を参考に進めたり。まずはPythonで書かれているという事で、Pythonの2.7を インストール。Cドライブのルートにインストールされるのがちょっとアレな感じ ですがまぁ良しとしよう。パスが通っていないので、MinGWのシェル上で追加したり。 続いてMercurialのソースアーカイブをダウンロード。無難にmercurial-1.9.3を使用。 説明書通りにやってもビルドできないらしいので、参考ページに従って、

python setup.py build --force -c mingw32
python setup.py install --force --skip-build

でビルド&インストール。インストールはC:/Python27/Scriptsの中にインストール されるという事で、コマンドラインから使いたければ、そういうバッチファイルを 用意するという仕組みらしい。そんな訳で、

#!/bin/sh
export PATH=/c/Python27:$PATH
python /c/Python27/Scripts/hg $@

というシェルスクリプトを/bin/hgとして置いてみたり。

gdcを試しにビルド。いつの間にか最初のconfigure実行で gmp/mpfr/mpcの ライブラリ検査が通らなくなっていたり。先日gmp/mpfrを新しい のに変えたのにmpcの方が追従してなくて、削除された(?) mpfrの関数をリンクしようとしてエラーになっていたり。mpcを再ビルドして 解決。そんな訳で、ビルドしたgdcの -v 表示は以下のような感じに。

$ gdc -v
Using built-in specs.
COLLECT_GCC=C:\MinGW\gdc031_2057_462_b\bin\gdc.exe
COLLECT_LTO_WRAPPER=c:/mingw/gdc031_2057_462_b/bin/../libexec/gcc/mingw32/4.6.2/lto-wrapper.exe
Target: mingw32
Configured with: ../configure --build=mingw32 --with-arch=i686 --enable-languages=c,d --prefix=/mingw/gdc031_2057_462_b --enable-threads --enable-fully-dynamic-string --enable-libstdcxx-debug --enable-version-specific-runtime-libs --disable-nls --disable-win32-registry --disable-symvers --disable-werror --enable-sjlj-exceptions --with-bugurl=https://bitbucket.org/goshawk/gdc/issue --disable-bootstrap --disable-shared
Thread model: win32
gcc version 4.6.2 20111026 (gdc 0.31 - r795:87241c8e754b, using dmd 2.057) (GCC)

最後のバージョン表示にgdcのリビジョンとIDが追加されるようになってみたり。 これでどのバージョンかを調べるのが簡単になるような気がしたりも。

ANIMAXで東のエデンの劇場版のIIをやってたり。これに合わせてか、昨日の深夜に 全11話放送していたのを見ていたり。本放送の時は途中の話をすっぽかしたり していたので話がよく判らなくなったのですが、なんとなくどういう流れなのか が判ったり。劇場版はIとIIがあるようです。劇場版Iの内容は知らないのですが、 ノイタミナ枠→劇場版II の流れでも、特に違和感無く繋がっている気がしたり。
個人的には、100億円では意外と大きな事ってできないよね?という気がしたりも。 20000人のニートをどうにかするったって、1億人のうちの0.02%にしか過ぎない 訳ですが、例えば100億円を20000人で分けると 50万円にしかならなくて、高々数ヶ月 くらいしか生活できないという金額とも言える訳です。最後に1億人に1円ずつ電子マネー を振り込むってシーンがありましたが、振込みに必要な手続きにかかる金額の方が 1円よりも遥かに大きいんじゃないか?という気がしたりもする訳です。 この辺の金銭感覚的なズレが観ててずっと違和感を感じる点だったようにも思ったりも。

2012/02/25

昼ごろ起床。

そういや、DMDのwritef()でreal型の表示桁数が gdcと異なる件。 DMDのwritef()で double型を表示するとどうなるんだ?と思い 表示してみたり。使用したコンパイラはDMD2.058。

writef("%3d %1.60e\n",i,elem) ;
writef("%3d %1.60e\n",i,cast(double)(elem)) ;

real elemは 1.0/cast(real)(i)、i=3の時の表示が以下。

  3 3.333333333333333333400000000000000000000000000000000000000000e-01
  3 3.333333333333333148200000000000000000000000000000000000000000e-01

型によらず有効桁数は小数点以下19桁まで表示するという感じみたい。というか、 real型を基準に表示しているという感じなのかしら?

gdcはソースツリー構造をgccに合わせる作業に取りかかるみたい。 そんなに時間はかからないだろうという感じみたいですが、2.058対応される のはもう少し先になりそうな予感。

2012/02/24

早くも無く遅くも無く。

並列破壊の件。最小コードで再現させてみたり。

import std.parallelism ;
import std.datetime ;
import std.stdio ;
import std.string ;
import std.math ;

void main(){
  
  auto buf1 = new real[480];
  auto buf2 = new real[480];
  
  writef("cpus=%d, PoolThreads=%d\n",totalCPUs,defaultPoolThreads()) ;

  StopWatch sw;
  
  sw.reset() ;
  sw.start() ;
  serial(buf1) ;
  sw.stop() ;
  writef("serial times:%s\n", sw.peek().msecs) ;

  sw.reset() ;
  sw.start() ;
  parallel(buf2) ;
  sw.stop() ;
  writef("parall times:%s\n", sw.peek().msecs) ;

  int chkres=0 ;
  for( int i=0 ; i<buf1.length ; i++ ){
    if( buf1[i]==buf2[i] ) continue ;
    writef("diff %3d:%1.60e %1.60e\n",i,buf1[i],buf2[i]) ;
    chkres++ ;
  }
  if( chkres!=0 ){
    writef("compre error!!!!!!!\n") ;
  }
}

void serial(real[] buf)
{
  foreach(i, ref elem; buf) {
    elem = 1.0/cast(real)(i) ;
//    synchronized{ writef("%3d %1.60e\n",i,elem) ; }
  }
}

void parallel(real[] buf)
{
  foreach(i, ref elem; taskPool.parallel(buf)) {
    elem = 1.0/cast(real)(i) ;
//    synchronized{ writef("%3d %1.60e\n",i,elem) ; }
  }
}

チェックするコードの方が多くてイマイチですが、問題の出るのは parallel()の中です。で、これを色々試してみたり。ざっくり以下の様な感じ。

   OK : gdc0.31        on Fedora13(VMware(2CPU設定)) ; gdc-revision=a92d4b1f144d
   OK : DMD2.057       on WindowsXP(論理CPU数=2)
   OK : DMD2.058       on WindowsXP(論理CPU数=2)
   NG : gdc0.31(MinGW) on WindowsXP(論理CPU数=2) ; gdc-revision=11ae589b9a71

一応途中の結果を見て(コメントアウトしてある各要素毎の計算結果表示を生かして) 計算する要素の順序がバラバラに動いているのも確認してます。
所で、結果をwritef()で確認していて、表示がコンパイラやプラットフォーム毎に 違っているのに気づいたり。

gdc(MinGW) :  3 3.333333333333333333423683514373792036167287733405828475952148e-001
gdc(Fedora):  3 3.333333333333333333423683514373792036167287733405828475952148e-01
DMD2.05[78]:  3 3.333333333333333333400000000000000000000000000000000000000000e-01

gdcはMinGWの方は指数が3桁になってます。gdcとDMDでは有効桁表示が 異なるようです。phobosのstd.format辺りで決まるのかと思っていたのですが、 コンパイラによって違いがあるのは何故?

2012/02/23

早くも無く遅くも無く。

並列化破壊の件。Webで検索していると、80bitFPUレジスタが一度メモリに ストアされると64bitに丸められて結果が変わる事があるというのを知ったり。 でも、これは結果をdoubleに格納した場合。real型は10バイトでストアする fstpt命令を使っているので問題無いような気が。

スレッドのコンテキスト切り替え時のレジスタ退避方法がまずくて リストアしたときにdoubleに丸められてしまう場合があるとか??

2012/02/22

早めに帰着。

並列化破壊の件。gdbで命令単位のステップ実行を行ってみて 動きを見てみたり。スレッドによって全く違う命令列を実行している ような事は無いってのは確認できたのですが、変になっている現場を 押さえる所までには至らず。あと、real型はFPUレジスタであるところのst[0-7] レジスタ上は10バイト(80bit)で、info regs ...で表示する事が可能 なのですが、メモリ上のreal型を表示する方法が無くて、レジスタ上の 値がメモリにどうストアされてるのかがイマイチよく判らなかったり。 因みに、gdc上は real.sizeof の値は12を返します。4byteにアライメント されているのでこういう事になっている模様。

2012/02/21

早くもなく遅くも無く。

並列化破壊の件。少し変な感じが見えたかも?

マンデルブロ集合の複素平面上の座標を計算するのですが、 その計算結果が怪しい感じになっている事が判ったり。

y=  0
C=-1.161029157483502693200966282560671061219181865453720092773438e+000,
  -2.991753325200145996161718575656607299606548622250556945800781e-001

y= 60
C=-1.161029157483502771697203570511192083358764648437500000000000e+000,
  -2.991753325200143809325936672394163906574249267578125000000000e-001

y=0は絵が壊れない方のスレッド、y=60は絵が壊れる方のスレッド、Cはそれぞれのy 初期複素平面上位置(creal型)です。y=60の方は何故か小数点以下50桁以降が無くなってます。 確かにこれだとダメかもなぁと思ったり。で、シングルスレッドだとどうか? と思い、同じ様に値を出してみたら以下のような感じ。

y=  0
C=-1.161029157483502693200966282560671061219181865453720092773438e+000,
  -2.991753325200145996161718575656607299606548622250556945800781e-001

y= 60
C=-1.161029157483502693200966282560671061219181865453720092773438e+000,
  -2.991753325200143645340358083961618262947013135999441146850586e-001

y=0もy=60も x=0のときを表示しています。この為、X座標に対応するC.reは 同じになってます。yに対応する C.imは異なる訳ですが、マルチスレッド時の 壊れる場合と違って値が途中で'0'になる感じではありません。

で、realとdoubleで 1.0/3.0 を計算してwritef()で表示させてみたのが以下。

ra/rb=   3.333333333333333333423683514373792036167287733405828475952148e-001
da/db=   3.333333333333333148296162562473909929394721984863281250000000e-001

有効桁数が思ったより少ないのは置いといて、最後の0の部分の感じ。 なんだか壊れた絵が出る時はrealじゃなくてdoubleで計算されているのか? と思ったりも。マンデルブロの計算では同じメソッドを異なるスレッドが実行するので、 変数型が違うという事は無いハズです。何故こういう感じになるのやら?

crealやrealで宣言していた変数を試しにcdoubleとdoubleに変更してみたり。 すると、全面モザイクで絵が壊れたのですが、値は以下の様になったり。

y=  0
C=-1.161029157483502771697203570511192083358764648437500000000000e+000,
  -2.991753325200146029771985922707244753837585449218750000000000e-001
y= 60
C=-1.161029157483502771697203570511192083358764648437500000000000e+000,
  -2.991753325200143809325936672394163906574249267578125000000000e-001

y=60の時のCが、最初の絵の壊れるスレッドの値と、見事に一致しました。 という訳で、realで書いてあるコードが、スレッドによって 何故かdoubleで 計算されているという事が確定したのですが、 どうしてそうなるのかは全く見当が付かず。謎過ぎる。

2012/02/20

早めに帰着。

並列化で絵が壊れる件を少し追いかけてみるも尻尾を掴めず。

あまりの眠さに急速停止。

2012/02/19

昼ごろ起床。

MPFRを使う為にD用にポーティングを用意してみたり。MPFRをCで使えば、 mpf2mpfr.hなる便利なヘッダが存在していて、本体コードは一切いじらずに mpf系関数をmpfr系関数に置き換えてくれる様ですが、Dではそういうのは できない(?)ので、手で本体コードをMPFRに対応する感じだったり。

結論から言うとやっぱダメ。シングルスレッドで実行すれば一応期待通りの 絵を描いてくれるので、マルチスレッドがダメという感じ。 mpfr_buildopt_tls_p() というTLSサポートでビルドしているか否かを 返す関数は non_zero を返す(即ちTLSサポート有りでビルドされている)ので、 何かしらバグってるか、Dとの相性が悪いか、その他色々原因があるのかも 知れません。でも追いかけきれず(^^;

GMP/MPFRを使わない方のマルチスレッド化。拡大率を上げていくと、 何故かスレッドによって結果が少し変わったり。元々GMP/MPFRを使わないと拡大率を 上げた場合に浮動小数点数解像度限界によりモザイク模様になる場合が あるのですが、受け持つスレッドによって解像度限界に達している場合と そうでない場合とがあったり。シングルスレッドだとどのピクセルも モザイク模様にならないので、マルチスレッドによりどこか壊れている ような気がしたりも。うーむ、なんかうまくいかないなぁ。

並列化で壊れた絵

2012/02/18

起きたら午後もいい時間。寝すぎ。

みすず学苑のTVCM。以前、電車の窓に広告が貼ってあったのを見たのですが、 あまりの謎さ加減に首を傾げた覚えがあったのを思い出したり。

先日のstd.parallelismを使う実験の続き。ちょっと勘違いしてましたが、 taskPool.parallel()を使うのは、MinGWのgdc-0.31でコンパイルしてもリンク に失敗しないし実行してもSegfaultしませんでした。 そんな訳で使用するスレッド数を変える方法などを調べたり試したり。

マンデルブロ集合プログラムをマルチスレッド化してみたり。 単純に1ライン(画像の横幅)分の計算を行うメソッドを用意して、それを taskPool.parallel()で画像の高さ分を並列化するという感じ。
ひとまずGMPを使わないD言語ネイティブな方は並列化できて、それとなく CPU使用率100%で動作するようになったのですが、GMPを使う方がダメっぽい。 そもそもスレッドセーフじゃないのかもと思ったのですが、GMPと マルチスレッドを組み合わせて使っている例がWebを検索しても見当たらず、 マルチスレッドが いけるのかいけないの情報も得られず。

んー、コードをあれこれいじって挙動を調べてみたのですが、 やっぱりGMPはスレッドセーフじゃないような気が。

GMPとMPFRの関係について勘違いをしてました。GMP内には 多倍長浮動小数点演算を行うmpf_*系の関数というのがあります。 これの上位(?)機能版がMPFRという事でした。Dのポーティングでは GMPだけしか行っていないので、MPFRは使っていないという事に なります。 そんな訳で、マンデルブロ集合プログラムはMPFRは使ってなくて、 GMPだけの使用になってますので、UseMPFRというスイッチは 正しくはUseMPF が正解です(^^;;;;

で、話はスレッドセーフに戻るのですが、GMPもMPFRもMinGWで gcc/gdcをコンパイルするようになった時に入れたきりなので、 GMPは4.x、MPFRは2.xでした。現在はGMPは5.0、MPFRは3.1になっている のですが、MPFRの方はTLSを用いてスレッドセーフになっている らしいというのが判ったり。因みに、ここんところを探っていて、 GMP内mpfとMPFRの違いに気づいた訳です(^^;

2012/02/17

早めに帰着。

アバター観たり。CM入るの結構邪魔に思ったり。しかた無いですが。

2012/02/16

早くも無く遅くも無く。

DMD2.058が来てたり。さて、gdcに来るかどうか.......

std.parallelismを使う実験。MinGWビルドではSegfaultでダメなのですが、 Fedoraの方では実行可能でした。

void serial(double[] logs)
{
  foreach(i, ref elem; logs) {
    elem = log(i + 1.0);
  }
}

void parallel(double[] logs)
{
  foreach(i, ref elem; taskPool.parallel(logs)) {
    elem = log(i + 1.0);
  }
}

のようにすれば簡単に並列化できるようです。なのですが、なぜ foreach()に 指定する集成体(Aggregate)の違いで並列実行が可能になるのか、仕組みが イマイチよく判らず。

因みに、Pentium4のHTなので せいぜい20%くらいの高速化にしかならなくて、 ちょっと残念な感じ。Core i7 とかのマルチコアCPUで試してみたくなります。

2012/02/15

早めに帰着。

あまりの眠さに急速停止。

2012/02/14

早めに帰着。

並列化を行うのを支援するphobosのライブラリに、std.parallelismなる ものがあるのですが、DMD2.053で追加された物のため、日本語訳がありません。 サンプルをコンパイルしてみたのですが、gdc031だとリンクに失敗したり。 例のgdcバグの変種だと思われます。 gdc030の最終版ではリンクに成功。でも、実行するとSegfaultしたり。 うまくいかないなぁ。

DMDの2.058はまだ出てません。gdcも2.058に追従してくるかはまだ不明。 gdcも大分壊れている気がしなくもありませんが、2.058の取り込みで直る だろうか?

2012/02/13

早めに帰着。

ちょろり調べ事をして終了。

2012/02/12

AM中に目が覚めつつも、もそもそしてたら午後もいい時間。

そういや録画に使っているHDDの空き容量が無くなったのですが、 自動削除で古い順に消えていってます。このとき、古いんだけどまだ一度も 見ていない物がどうなるか?と思っていたのですが、見ているかどうかに 関係無く古い順に消えてくというのが判ったり。それにしても2TBも あっという間に埋まってしまうもんなんだなぁ(^^;

2012/02/11

起きたら午後もいい時間。寝すぎ。

gdcにAndroid対応がマージされてたり。

2012/02/10

早めに帰着。

あまりの眠さに急速停止。

2012/02/09

気持ち早めに帰着。

OpenGL描画をGDIなBITMAPに行う方法を調べてました。一応できる事は 判ったのですが、OpenGLの glGetString(GL_RENDERER)とglGetString(GL_VERSION)が、「GDI Generic 1.1.0」を 返していて、シェーダーとかは使えないという感じだったり。 GDIを使うと文字表示など割と自由になるので、用途によっては 使い勝手がかなり上がると思うのですが、描画性能はかなり落ちる ようです。なかなか良いとこ取りにはならないと言ったところでしょうか。

2012/02/08

少し早めに帰着。

ちょろっと調べ事。

2012/02/07

気持ち早めに帰着。

ちょっと調べ事。

2012/02/06

気持ち早めに帰着。

今週はgdcの動きが無いな。

そういや、以前、 std/socketstream.dが変なシンボルを要求してリンクに失敗する というのがありましたが(てかありますが)、それとほぼ同じ リンクエラーについての報告がgdcの掲示板に 挙がっていたり。 これで正式に直るであろう。

2012/02/05

AM中に起床。

少しマシになった所で洗濯したり買出しに出たり。

「ONEPIECE(65)」。なるほどこういう展開になりますか。 最後はどう決着が付くんだろう。続きが気になります。

2012/02/04

一日中寝てたり。

ちょろっと起きては、しんどくなって寝ての繰り返し。

2012/02/03

早めに帰着。

あまり回復せず急速停止。

2012/02/02

早くも無く遅くも無く。

絶不調で急速停止。

2012/02/01

気持ち早めに帰着。なんか喉の調子が悪いかも。

gcc-4.7.x対応のMinGW gdcでコンパイルした実行バイナリがずっこける件を 少し調べてみたり。rt/dmain2.d というコードの中の unittest実行で ずっこけている事が判ってみたり。更に追いかけてみると foreach( m; ModuleInfo ){...} というコードがあり、mがnullでなければ m.unitTestが実行されてモジュール毎にunittestが実行されるという仕掛け のようです。で、この m に謎の値が入っている場合があって、 Segfaultするという流れ。ModuleInfoをgdbで表示できるのかな?と 思ったのですが表示できず。うーむ。


TOP PREV