上へ

開発メモ

2003/07/06 画像処理

周囲8近傍要素とのソーティングが遅い。毎回9画素について挿入方でソートしていのを選択法にすればもう少し速くなりそうだけど、半減とはいかないだろう。注目画素をずらすたびに増えた3画素、減った3画素についてソートするように作り直してみた。・・・変わらなかった。

MMX命令使うように変えてみるか、大小比較と移動を下のようなコードでやって、アルゴリズムはバブルソート使うとすると、比較回数は1+2+3+・・・+8=36回/4画素、8画素バイトニックソート+1画素バブルソートとするともう少し速くなって6(1+2+3)×4+8=32回/4画素。CPU の並列性によってはもう少し早くなるけど・・・。

MMA, MMB → MMC=MAX(MMA, MMB), MMD=MIN(MMA, MMB)
    MOVQ        MME, MMA
    PCMPGT[BWD] MME, MMB    // MME 比較マスク

    MOVQ        MMC, MME
    MOVQ        MMD, MME
    PAND        MMC, MMA
    PANDN       MMD, MMB
    POR         MMC, MMD    // MAX(MMA, MMB)

    MOVQ        MMD, MME
    PAND        MMD, MMB
    PANDN       MME, MMA
    POR         MMD, MME    // MIN(MMA, MMB)
→結局、バブルソート+キャッシュ+マージソート、比較回数(1+2)+3×3+5×3=27回/4画素にした。

2003/07/09 画像処理

処理にもよるけど MMX を使った場合のメモリアライメントがボトルネックとして浮上してきた。 メモリ境界をまたぐペナルティがPentium Pro,II で 6〜9クロック程度なので、一番内側のループが数クロック程度と小さい場合メモリアライメントが効いてくるらしい。

MMX用に 8 byte(64bit) 境界のポインタも返すメモリアロケートルーチン
function GetMemAlign(var P: Pointer; Size: Integer; Align: Integer = 8): Pointer;
// Align バイト単位アライメント指定
begin
  Dec(Align);
  GetMem(P, Size + Align);
  Result := Pointer((Integer(P) + Align) and (not Align));
end;
使用例
  PMMX := GetMemAlign(P, Size, 8);    // SSE 命令から使う場合は 16
  ... PMMX を使ってアクセス
  FreeMem(P);

2003/07/10 北海道(その1)

超割で、羽田→新千歳空港へ、平日ということもあり機内は空席が目立つ。
新千歳空港から札幌まで快速エアポート(1040円)。ここで手持ち1万円を切った動揺で切符を取り忘れる。戻ってみると券売機が止まっていて(←迷惑な奴(^^)、駅員さん「誰〜」、おれ「多分私ではないかと〜」、駅員さん「はい」。
潔白のつもりだけど、値段とか確認無しかぁ、北海道良いとこだ。
それにしても ATM を見つけないと。

札幌駅について、先ずは宿を探す。・・・夏場の北海道を甘く見すぎていた。平日だというのにどこの宿も一杯。サウナか公園デビューの覚悟を決めた頃、やっと空きが見つかる。気が付けば ATM が閉まっている時間に・・・一時間以上電話していたらしい。携帯のバッテリーも心もとなくなってきた、充電器もってきていないのに。

仕方ない、とりあえずラーメン。
ラーメン屋にて、客が去ってテーブルを片付けていたおばちゃんが、カウンターの隅で食べてるおねーちゃんに「空いたから広いところにいきな」と言って、片付けたテーブルを勧めていた。初めて見る光景だけど、北海道では普通なのか?北海道良いとこだ。

晩飯はススキノ行ってうに丼いくら丼と思っていたけど、雨だし手持ちも心もとないし宿でおとなしくしてることに。

2003/07/11 北海道(その2)

ラーメン屋のはしご中、地下街で携帯の店を見つけたので、充電器売ってないか聞いてみると。「中古だし差し上げます」
北海道良いとこだぁ〜。
札幌からバスで40分程の定山渓の温泉宿に泊まる。

2003/07/12 北海道(その3)

朝風呂の後、札幌に戻って、昨日の携帯の店にお礼と充電器返しに行って、これも縁ということで携帯買ってしまう。もしかして術中にはまったのか?(^^;
二条市場でうにいくら丼食べて、お土産買って少し早めに空港へ、キャンセル待ちで乗ろうと思っていたらものすごい混んでる。
仕方なく荷物をコインロッカーに預けてうろうろしていると、空港レストランの商品サンプルが見えてしまった。
・・・二条市場のうに丼より安くて大きい(実物は見てないので分からないけど)、でも食ってく時間も腹の余裕も無い。
言いようの無い後悔と共に帰省。

2003/07/19 画像処理

正規化相関のサブピクセル補間、評価値の補間ではどうも精度が出ない。サーチパターンをサブピクセルシフトして評価するか、サーチパターン、背景ともに補間拡大して評価するかしないといけない感じだ。
サーチパターンをシフトするのは回転サーチの延長線上で出来るし速度的に有利なので惹かれているけど、精度的には両方補間拡大か。でも拡大、評価ともに激遅だな。

拡大の高速化は整数倍のBi-Cubic 補間拡大に特化した関数作って、
評価の高速化は拡大率変えながら絞り込んでいく感じか。

これでどの程度速度と精度が出るかだけど・・・しばらく保留せざるを得ない状況。つまらん。

2003/07/21 画像処理

元画像の Bi-Cubic 補間2倍拡大を n 回繰り返したものと、元画像を Bi-Cubic 補間 2^n 倍拡大したもので違いがでるか調べてみた。見た目ではっきりした違いは無いが一応ある。式の展開は保留。

それよりモスキートノイズがかなり目に付く、Bi-Cubic で使われる sinc 関数は1ピクセルを回折円と仮定して、輝点の周辺に暗い円を作るので避けられない気がする。Bi-Cubic で良いのかも含めてかなり真面目に調べないとサブピクセル補間精度は出そうにない感じだ。

画像処理で標準的に使われる画像 SIDBA標準画像の一部画像処理技術の発展に最も貢献した人物 まさか既に50歳過ぎてるとは・・・それにしても見慣れた顔なので妙に懐かしいものがあるな。

2003/07/22 tcalc.dll

ビット演算(and & or | xor not ~)、剰余(mod %)、階乗(fact !)、組み合わせ演算(PERMUT P CONBIN C)追加
中身的にはかなり変えたのでなにかあれば連絡を。

2003/07/28 lua

Delphi にスクリプト言語を組み込みたい。
  • 本格的な言語
  • サイズ的に軽い
  • 独特の概念を強要しない(兼業プログラマが多いので(*))
  • スクリプト側からも Delphi の関数が dll 化しないで呼べる
という条件で考えて lua (日本語4.0 日本語5.0) を組込んでみる。lua は C のソースコードで配布されていて、各自コンパイルしてライブラリを作って、アプリケーションからはライブラリ関数呼び出しという形で使うらしい。

ダウンロードしてみると 「Lua の構築は Unix システム上ではとても簡単です」 とのこと、Makefile その他を見てみると Borland C++ でコンパイルを通すように頑張るより gcc を使った方が楽そう。cygwin 環境の gcc でコンパイルするとバイナリが cygwin 依存になってしまうので mingw32 でコンパイル通ってくれれば良いんだけど・・・
つづく。

(*)pythonScheme も強力な言語なんだけど、 python はインデントに慣れない人はとことん慣れないだろうし、Scheme は頭が Lisp に切り替わっていて、なおかつ Emacs 環境がないと辛いし。

2003/07/29 lua

mingw32 の GNU make ver 3.77 と gcc ver 2.91.66 で各ディレクトリ毎 make(maingw32 古いのと、環境設定をあまり詰めてないせいか make の多重起動がうまく行かないので)であっさりコンパイル成功、FAQ を見てみると ANSI C 準拠に力を入れているとのことなので、Makefile を書くだけで Borland C++ フリーウェア版でもコンパイルできたかもしれない。

目的は Delphi から使いたいので dll を作らないと、gcc で dll 作るのって面倒なんだよな・・・。
gcc 2.95.2-1からは -shared オプションでお手軽に作れるらしいけど、作者の環境でダウンロードしたら一晩かかってしまうので gcc アップデートは断念。gcc 2.91.66 で強行することに。

gcc 2.91.66 で dll を作るサンプルバッチ、無理やりです。
rem *** Create the import library for the dll ***
dlltool --dllname lua.dll --def lua.def --output-lib libdll.a  

rem *** Compile the dll ***
gcc -c -o luadll.o luadll.c

rem *** Link the dll ***
gcc -s -mdll -o lua.dll -Wl,--base-file,dll.b luadll.o ..\src\*.o ..\src\lib\*.o
dlltool --dllname lua.dll --base-file dll.b --output-exp dll.e --def lua.def
gcc -s -mdll -o lua.dll -Wl,--base-file,dll.b luadll.o -Wl,dll.e ..\src\*.o ..\src\lib\*.o
dlltool --dllname lua.dll --base-file dll.b --output-exp dll.e --def lua.def
gcc -s -mdll -o lua.dll luadll.o -Wl,dll.e ..\src\*.o ..\src\lib\*.o

rem *** Delete temporary files from dll linking ***
del dll.b 
del dll.e 
dlltool を使って def ファイル作成・・・失敗、nm liblua.a liblualib.a でシンボル情報を抜き出して、アドレスと先頭のアンダースコアを消して、sort | uniq で無理やり def ファイル作成・・・リンクエラーが起こるので、余分に抜き出した static 関数を消しす・・・gcc が -lm オプションを認識しないので消す(算術関数リンクのために必要なはずなんだけど?)・・・でやっと dll 完成。

lua.c を参考に delphi から呼んでみるととりあえず動いた、算術関数も使えているみたい。lua への delpih 関数の登録処理は結構いい感じだし、標準入出力の切り替えも出来そう、覚えるだけの価値はありそうなので、後でまとめよう(今は時間が無い)こんな動けばOKの突貫工事ばっかやってると消耗するだけで実力付かないし。

というわけで時間が出来たら
  • コンパイルの自動化(Borland C++ フリーウェア版用 Makefile の作成?)
  • lua スタック、テーブルモニタ?デバッガ?の作成
  • lua 例外の動作把握と使用方針決め
  • delphi、lua 処理分割の方針決め