2010-11-28

jom: 並列nmake

jomというQtの作っているビルドツールを見つけた。

Visual C++付属のmakeであるnmakeのクローンらしい。違いはマルチコア用に並列ビルドができること。バイナリが単独で公開されているので最近利用している。

gmakeは-j 5とすると5プロセスで並列でビルドを走らせてくれるが、nmakeは未だにそのサポートがない。cl /MP a.c b.cというオプションで並行でコンパイルはしてくれるが、makeを使う場合ソースファイルはひとつずつしか処理されないので、このオプションは使えない。

  • MSVCでプログラムを作っているのに
  • Visual Studioではなくnmakeを使っていて
  • nmake用のMakefileを捨てたくないが
  • コンパイル速度を上げたい

というかなりニッチな需要を満たしてくれる。(というか、本来はQtユーザ用なのだと思う)

ベンチマーク

手元の自作ゲームを一からビルドする時間を計ってみた。3GHzのCore 2 Duoで試した。

『体力制チェス』 (総計9461行、53ヘッダ+47ソース=100ファイル)

--nmakejom
プリコンパイルヘッダなし25.2 秒14.23 秒
プリコンパイルヘッダあり5.0 秒3.6 秒

『加速度センサー小品集』 (総計10067行、51ヘッダ+57ソース=108ファイル)

--nmakejom
プリコンパイルヘッダなし33.6 秒18.5 秒
プリコンパイルヘッダあり7.2 秒4.9 秒

それなりに効果はあるようだ。(ディスクキャッシュの話があるので細かい数字は信用できないが)

移行

クローンとはいえ、既存のMakefileを全くそのまま使えたわけではない。

依存関係を見て並列的に処理できるところを分けるので、依存関係をきちんと設定していないと順不同になるところが出てくる。最初に試したときはmkdirが偶然うまくいっていた所がつまづいた。

Makefile内でINCLUDE環境変数を書き換えてインクルードパスを無理やり設定していたが、その方法が通じなかった。CFLAGSに直接追加することで解決した。INCLUDEをMakefile内で設定してもコンパイラに伝わらないようだ。

下位互換性はあるので、とりあえず仲間内では自分だけ使おうと思っている。

Nov 28th, 2010 11:10pm
(copied from tumblr)

2010-09-01

マンデルブロ/ジュリア/バーニングシップ集合ビューア

Mandelbrot

よくあるマンデルブロー集合のビューアを作った。マウスだけでつかんで4次元で切片を動かせる。緑が発散までの回数、赤青は発散した向き。

ダウンロード

mandelbrot.zip

gist:525284

操作

操作効果
ドラッグ移動
ダブルクリック移動
マウスホイール拡大・縮小
右ドラッグ定数の調整
右クリックモード切り替え (ジュリア集合とか)
左クリックしながらマウスホイール繰り返し回数の調整
右クリックしながらマウスホイールモード切り替え (ジュリア集合とか)
マウスホイールをクリックリセット

(copied from tumblr)

2010-05-04

C言語のCって何?

「何の略でもない」というのが本来の答えだが、元をたどると3つくらい答えがあるらしい。(『C++の設計と進化』から)

「B言語の次」

「Bって何?」

「BCPLをインタプリタに設計し直したもの」

「BCPLって何?」

「Basic CPLの略」

「Basic CPLって何?」

「CPLという言語を設計し直したもの」

「CPLって何?」

「C. Programming Language の略。Cは以下のどれか」

  • Cambridge (開発した大学の片方の名前)
  • Christopher (設計者の名前)
  • Combined (公式にはこれ。「共同開発」の意)

結局C言語の元はC言語ということになる。

途中の説明を飛ばして「C言語のCからだよ」と言えばややこしくなっていいかもしれない。

(copied from tumblr)

2010-03-23

プレーンテキストの画像形式

少し前から「プレーンテキストの画像形式」というものを探していた。

レイトレーシングなど、絵が出力結果であるプログラムを作って遊んでいると、レンダリングの結果を出す先に困ることがある。

画面表示のできるライブラリを持ってくるのも大仰だ。画像に保存したいところだ。しかも、printfとかで適当に。

BMPの構造体の定義や、PNGやGIFのアルゴリズムを空で書き下すには修行が必要だ。(windows.hは反則)

UNIX系列であればPNMというかなり理想的な形式がある。しかし、残念ながらWindows付属のビューアでは見られない。

SVG形式も考えたが、これはビットマップには向かない。rectを一面に並べる変換器を作ってみたら200KB程度の画像が9MBに膨れ上がった。

サイズはテキストの時点である程度諦めるべきところだが、どちらにしろ表示が極端に重たかった。

SVGの形式を眺めていて、HTMLで一時期流行った遊びを思い出した。

「tableタグでbgcolorを指定したtdをひたすら並べる」

<code><html>
  <head>
    <style>
      tr{height:1px}
      td{width:1px}
    </style>
  </head>
  <body>
    <table border="0" cellpadding="0" cellspacing="0">
      <tr><td bgcolor="#000000"></td><td bgcolor="#000000"></td><td bgcolor="#000000"></td><td...
      <tr><td bgcolor="#000000"></td><td bgcolor="#000000"></td><td bgcolor="#000000"></td><td...
      ...
    </table>
  </body>
</html>
</code>

本当にfprintfしか使わない実装。

void dump(int w, int h, const char *pixels, FILE *fp)
{
    int x, y;

    fprintf(fp, "<html><head><style>tr{height:1px}td{width:1px}</style></head><body><table cellpadding=0 cellspacing=0 width=%d height=%d>", w, h);

    for(y=0; y<h; y++)
    {
        fprintf(fp, "<tr>");

        for(x=0; x<w; x++)
        {
            fprintf(fp, "<td bgcolor=#%02x%02x%02x></td>", pixels[x + y * w], pixels[x + y * w + 1], pixels[x + y * w + 2]);
        }

        fprintf(fp, "</tr>");
    }

    fprintf(fp, "</body></html>");
}

これでとりあえずブラウザに表示させてプリントスクリーンすれば画像になる。

いまどきならCanvasでImageDataなどを使うのかもしれない。

(copied from tumblr)

2010-02-17

Mix_LoadMUS_RW の引数に int freesrc がない件

最近ZinniaさんのSDL_RWops解説を読み直して、fopen/fcloseをRWops系の関数で書き直した。これを抽象化の点として、そのうち暗号化したzipなどから読ませるようにしたいと思う。
画像ファイル(SDL_Image)は問題なく置き換えることができたが、音声ファイル(SDL_Mixer)の部分で落ちるようになった。
検索でGameDev.netのフォーラムのトピックを見つけた。以下会話の流れ。


Mix_LoadMUS_RWで落ちる。どういうこと?
<状況説明とMix_LoadMUS_RWを使ったコード。SDL_Mixerのバージョンは1.2.7で、プラットフォームはOS X>


SDL_mixerのソース(load_ogg.c, music.c, music_ogg.c)を読んでみた。
Ogg形式ならMix_LoadWAV_RW()が代わりに使える。
ただ、データを内部でコピーするから、長い音楽には向かない。
5MB程度のOggでも、メモリ上に解凍すると45MBになってしまう。
Mix_LoadMUS() はディスクから少しずつ解凍しながらストリーミングするから、4KB程度のバッファですむ。
Ogg形式の場合は、Vorbisライブラリがストリーミングの処理を直接扱う。つまり、Vorbisがファイルを開いて、直接FILE *からチャンクを読んでいく。
Mix_LoadMUS_RW() の場合はSDL_RWopsをコピーする手段が無いから、引数に渡したものをそのまま使うしかない。つまり、処理が帰ってきてもfreeされないことになる。
要は、引数に渡したRWopsをfreeせず、 SDL_RWclose(rw) も使わなければOK。
(注:普段私はSDL_Mixerを使わない)


ありがとう。私も読んだけどそこまでは読み取れなかった。
まだ疑問が残っているのは、これが二重freeのエラーになることだ。

Mix_FreeMusic(music);
SDL_FreeRW(rwops);

Mix_FreeMusic()がfreeしているということ?ソースからはわからなかったけど。
まあ、二重free以外は全部うまくいっています。ありがとう。


その通り。RWopsはMix_FreeMusic()でfreeされる。
この処理はVorbisライブラリ(正確に言うと、vorbisfile.c)側でしているから、SDL_Mixerのソースにはない。
どういたしまして :)


なるほど。丁寧な解説をありがとう。Thanks again :)



ということで、Mix_LoadMUS_RWに渡したRWopsはMix_FreeMusicが閉じてくれるらしい。
手元のコードもSDL_RWcloseを省くとうまく動いた。

(copied from tumblr)