2010/06/21
言語Xは速い、というのは
昨日のエントリへのリンクが拡散しているようなのでちょっと補足めいた雑談。
定量的な速度の話になった時点で、純粋な言語そのものではなく 処理系込みの話になる、っていうのはいちいち断らなくてもいい…よね? 「実際にそういうことができる処理系が今存在しているか」っていうのは 言語選択に影響を与えるファクタであろうと思う。
普通に書いたLispと普通に書いたCならCの方がずっと速い。 Lisp版の方が安全で、簡潔で、汎用的だろうけれど。 違いが出るのはそっからどこまで追い込めるかという伸びしろの部分なんだけど、 それを重視すべきかどうかというのはプロジェクトに依存する。 コンパイラを出し抜いてまで性能を稼ぐ必要のある案件っていうのは 全体の割合では減ってきてはいるだろうと思う (もっとも、サーバサイドの スケーラビリティが重視される流れになって、「性能が足りなければ マシンを増やせばいいじゃない」とか「2年待てばチップが速くなるよ」 なんて能天気に構えていられなくなってきてはいると思うけど)。
個人的にはCommon Lispの処理系はこの先もっと頑張らないとまずいんじゃないか と思ってる。といっても普段使ってる処理系はAllegroだけだし、それも 限界まで使い込んでるわけじゃないので外してるかもしれないけど。
- inter-proceduralな、あるいはプログラム全体を見ての最適化はもう C/C++では普通だけれど、Common Lispの場合、関数単位でのダイナミックな 置き換えがいつでも可能という前提があるため、ちょっとこの分野で遅れを 取っているのではなかろうか。インライン展開程度ならマクロで、 inter-proceduralな情報を利用することで可能になる型チェックの 省略などについては人手で型宣言をつけてやることで補償できるけれど、 ソフトウェアの規模が増大すれば、自動化しないと破綻するだろうし。
- Lisp族というくくりで言えば、Stalinがwhole program analysisの 強さは証明しちゃってるのだけど、コンパイル時間が増大するのは大問題。 C++もそれでつまづいてる。ここはひとつ、動的言語の誇りにかけて、 全プログラム解析とインクリメンタルな関数の置き換えを両立させて 欲しいものだ。例えば関数を動的に置き換えると関数毎に閉じた最適化に リセットされるけど、そのままほっとくと勝手に解析が進んで次第に 最適化の範囲が広がってくとか。
- 型というかメタ情報に対するサポートってのはもっとあっていいと 思うんだよね。Allegro CLだとfixnumをメモリアドレスと見なして 生メモリに直接触れるので(正確には8byte alignedなアドレスを3bitシフトした 値をfixnumで扱うんだけど、fixnumのタグが000なので ネイティブコードレベルではint64_t*で書いてるのと同じコードになる)、 例えばそれを使ってshared memoryをmmapした領域に 自分でメモリアロケータを書けたりするんだけど、 Lisp的にはアドレスとfixnumの区別がつかないんで、 void*とintptr_tの区別があるCよりも状況が悪い。 がっつり型検査しろとは言わないけど、「ここはaligned pointerだよ」、とか 「ここはaligned pointer同士の差分だよ」とか宣言しといたら ある程度自動的に矛盾箇所 (差分だけ使ってmemrefしてるとか) は 検出できるだろう。少なくともそういう検証ルーチンをコンパイラに組み込める フックがあったらいいなあ。自分でcode walker書けばできるんだけどさ。
「言語よりは環境の問題」と言えばそうなのかもしれないけれど、 マクロで低レベルコードを吐かせたり、なんていう話になってくると 言語と処理系と開発環境は相互に支えあってて切り離しては語れないよなあ、 とも思う。処理系と独立した言語仕様があること自体は、 プログラムの正当性の検証という見地から重要なんだけどね。
Tags: Programming, Lisp
Post a comment