Hatena::ブログ(Diary)

誰にも見られていないはずのブログ

2008-10-23

VFP関連のメモ

とりあえずVFPを使う場合の最小のスタートアップコード。 _stack_initは適当にリンカスクリプトにでも書く事にする。とりあえずSVC modeのスタックだけ初期化しておけばいいだろう。

OSの場合は、普通VFP命令を実行して、Undefined Instructionが起こってから例外ハンドラで有効にするんだろうけど。使わないのにいちいちVFPレジスタの退避と復帰をしてたら効率悪いもんな。CPU初期化部分を大分省いてるけど、そんなのはデバッガがやってくれるから関係ない。

.arm
.text
.globl _start
_start:
        /* Initialize Stack */
        mov                 r0, #0x13+0xc0
        msr                 cpsr, r0
        ldr                 sp, stack_init
        bic                 sp, sp, #3

        /* Full access to VFP */
        mrc                 p15, 0, r0, c1, c0, 2
        orr                 r0, r0, #(0xf << 20)
        mcr                 p15, 0, r0, c1, c0, 2

        /* Enable VFP function */
        mov                 r0, #0x40000000
        fmxr                fpexc, r0
        b                   main

stack_init:
        .long           _stack_init

マルチコア

カーネル空間はデマンドページングじゃないのに、あるタイミングでアクセスできなければならない空間をリードしにいくとアボートする。MMUで変換をかけてみたら、変な物理アドレスマッピングされている。しかもそのアドレスはMMUの変換テーブルがあるところだし、意味がわからない。論物変換できると見せかけて、実はページフォールトしてんのかなあ。一応対策はしてるはずなんだが。

とりあえず変なところでアボートしたら、フォールトと見なすようにするか。

2008-10-14

STM

GCCにSTM(Software Transactional Memory)ブランチが新しく作成された模様。

http://www.hipeac.net/node/2419

ARMv7 MP Extentions からはcmpxchg8b命令があるから結構楽に実装できそうだな。というか、これがないと完全には実装できないのか。

2008-10-09

最初の言葉

息子が「アンパンマン」と言ったらしい。パパとかママなんて全然言ってくれないのに。うれしいけど何か複雑な気分ではある。

LTOもどき

そういやGCCでは、4.1ぐらいから-fwhole-programオプションを付けると、複数のソースファイルを1つと見なす事が出来るためIPOが実行できる。なんかインチキくさいぞ。ちなみにこの辺の最適化はcgraphunit.cに書かれている

当然こんなのは無理

 gcc -c -fwhole-program a.c
 gcc -c -fwhole-program b.c
 gcc a.o b.o -o out

こうしないといけない

 gcc -fwhole-program a.c b.c -o out

2008-10-06

LTO

GCC summitを見学しにいったときに、CodeSourceryのMark Mitchellと話をする機会があった。彼はGCCC++フロントエンドのメンテナで、リリースマネージャーでもある。リンク時最適化については、組み込みの世界でも非常に有用だし、待ち望んでる人達もいるので頑張って下さいと言ってきた。今考えてみれば、お前もコミットしろよという感じであるが、言語は日本語しかわからない俺にとってはハードルが高いのである。C言語とか何をやってんのかさっぱりわからん。でもソース見てたら何か出来そうな気がしてきた。気がするだけ。

GCCのltoが結構活発に開発が進められている。whopr(Whole Program Optimization)やgimple tuplesなんかとも連動して、最近はGoogleの人達がよくコードをコミットしている。CodeSourceryはどうしたんだ? SourceryG++のサポートCPUが増えたし、4.3ベースのリリースが待ってたりするから忙しいのかな?

それはともかく、-fwpa -fltrans とかいうオプションが増えた。基本的には前からあった-flto1発でいけるみたいだが、他のオプションは何が違うのか気になるところだ(良くわかってない)。メーリングリストでは、ユーザが混乱するからいっぱい似たようなオプション作るのはやめようぜという意見が出てきたので、最終的には-fltoと-fwpaぐらいになるのかもしれない。

Link-Time Optimizationといってはいるが、別にリンカで最適化してくれるわけではなく(GCCのブランチなんだから当たり前だけど...)、コンパイル過程で作られるコールグラフの情報をオブジェクト単位で残しておき、リンカが呼ばれる直前にもう1度GCCを起動して、全てのオブジェクトを入力する。そして、ローカルなコールグラフを全部ロードしてグローバルなコールグラフを作ればIPOが出来るじゃん、という寸法である。実際、2008/10/3の時点では、各オブジェクト毎に以下のようなセクションが増えてた。

 [ 4] .gnu.lto_internal  PROGBITS
 [ 5] .gnu.lto_main      PROGBITS
 [ 6] .gnu.lto_.static   PROGBITS
 [ 7] .gnu.lto_.cgraph   PROGBITS
 [ 8] .gnu.lto_.decls    PROGBITS
 [ 9] .gnu.lto_.symtab   PROGBITS

ltoのコンパイラドライバ(?)のlto.cを見たが、確かにリンカが起動する直前にGCCを起動してたし、グローバルなコールグラフを作成してから、IPAのパス(今のところインライン展開だけ)が実行されてた。ソースのコメントに書いてあったが、まだ色々問題があるようだ。

ltoプロジェクトを進めている人達は、メモリ効率とコンパイル時間を非常に気にしていて、特にコンパイル時間は倍近くなる可能性もあるため、結構悩んでいるようである。ただでさえGCCコンパイル遅いのに、更に遅くなったら誰が使うんじゃいとか言ってた気がするが、たぶん俺なら喜んで使うと思う。

どうでもいいけど、llvmのbcにはコールグラフの情報が含まれてるんでしょうね。ARMのコンパイラはそんなのが入ってるようなセクションあったかなあ。

10/16追記: -fwpaオプションはさっくりと無くなって -fwhoprに変わった。

デバッガ

個人的には、ソフトの開発にはデバッガが必須であると考えている。しかし、プロのエンジニアの人たちに聞いてみても、デバッガを使っていない人が驚くほど多い。ちゃんとした(?)ソフトウェアの開発現場に居たことがないのでよくわからないが、みんなどうやって開発してるんだろうか。

バグをほとんど出さないような天才とか、頭の中にCPUエミュレータを搭載していてステップ実行なんかが出来てしまうような特異能力者ならまだしも、普通にコードを書いて、その後のバグ取りに時間をかけている開発者にとって、デバッガは無くてはならないものだと思う。現場でほとんど使われていないような高級言語とか、最近流行のLightWeightなものに関しては知りません。

確かにprintfを使って、任意の時点での環境をそれなりに把握することができるし、これを繰り返せば原因は特定できる。熟練したソフトウェア開発者であれば、経験からバグの原因を短い時間で特定することができるかもしれない(熟練した開発者じゃないのでわからないけど)。しかし、デバッガを使えば、それほどの熟練者でなくとも、驚くほど短い時間で問題を見つける事が可能である。正しく解決できるかどうかは別だが。

デバッグの準備

基本的にはコンパイル時にデバッグ情報を付加すれば、ソースレベルでのデバッグが可能である。ただし、最適化をはずさないと非常にデバッグしづらい。デバッガの歴史は最適化との戦いの歴史である(そうでもない)。デバッグ情報も進化する余地が十分残っているのだが、変数が削除されてしまったり、命令の順序がガラッと変わったりしてしまうと、もうどうしようもない。

というわけで、この際思い切ってGCCの場合には-O0オプション最適化をはずす事にする。デバッグ情報を付加するオプションは -g -gstabs -gstabs+など。-g はDWARFで、-gstabs -gstabs+ はstabのデバッグ情報フォーマットである。DWARF2の場合は、同じヘッダをいっぱいインクルードすると、その数だけデバッグ情報が出てしまうのでサイズがでかくなってしまう。stabは大丈夫。DWARF3でも、この辺は改良されるみたい。

最適化について

最適化をはずさないとデバッグしづらいとは書いたが、ソースレベルデバッグできないわけではない。ただ、ソース上でステップ実行したりすると、あっちこっちに飛んでいってしまって、正確にどこを実行しているのかを把握するのは難しい。ローカル変数なんかも、無くなってしまったものは当然ながら表示されない。

gdbでは、optimized outとか表示されたような気がする。gccはvar-trackingとかで、最適化されてもローカル変数が今どこにあるのかという情報を出来るだけ吐こうとするが、完全に正確というわけではない。gccのプロジェクト内では、現在もデバッグ情報の精度向上について頑張っている人もいるが、最適化のパスを書いてる人達はあまり考えてないような気がする。最適化が進めば進むほど、ソースコードと最終的なコードの対応がつかなくなり、最適化したプログラムのソースレベルデバッグが更に困難になっていくのは避けられない。

んじゃあんまりデバッグに影響を与えないような最適化のパスだけ通せばいいんじゃねーのって事で、-Ogオプションなんかも提案されているが、動きがあるんだか無いんだかわからない。

プログラムのロード

ビルドして出来たプログラムデバッガでロードする。たいていの場合は、デバッガのロードコマンドを使えば良いだけだが、例えばJTAG-ICE経由でターゲットのメモリに転送する場合などは、メモリアドレスを指定しなければいけないかもしれない。デバッグ情報にロードするべき各セクションのアドレスが書いてあるので、多分大丈夫だろうけど、MMUが無効の場合にLinuxカーネルを転送する時なんかは(普通はそうだろう)、物理アドレスでちゃんと指定してやる必要がある。デバッグ情報に書いてあるアドレスは論理アドレスだし。

続きはいつかかく

2008-05-30

また放置してた

勤務先の飲食店が最近忙しくてあんまり書けないなあ。

あんまり書く気がないだけという噂もあるが。

2008-05-13

眠れない

明日は朝早く家を出なきゃいけないのに、こういうときに限って眠れない。アレルギーを抑える薬を睡眠薬代わりに飲むという選択肢もないことはないのだが、非常に強い薬で、他の副作用もバリバリなのでやめておくことにする。

リンク時最適化

ADSのリンカ

ARM純正のツールであるADS付属のリンカを実際に使ってみたが、特に未使用関数を削除している雰囲気はなかった。マニュアルを見てみたら、C++の仮想関数の削除をするらしい。一応コールグラフを表示させると、普通の関数でもUNUSEDのキーワードがついてるんだけどなあ。何か他にオプションがあるんだろうか。ファイルをまたがったインライン展開や、コンパイラへのフィードバックは見ていない。

GCC Link time optimization

ltoは数あるGCCのプロジェクトの中の1つで、2005年頃にアナウンスされたようだ。CodeSourceryの中の人たちが主に実装を担当しているようである。

GCC Link-time optimization

ビルドして少しだけ使ってみた。configureオプション

 --enable-languages=lto

としてビルドすると、lto1が作成される。あとは

 gcc -B. -flto hoge.c -o out

みたいな感じでコンパイルすればリンク時の最適化がかかる。1回ファイルごとにコンパイルして生成した中間オブジェクトファイルを、もう一度全て入力して最適化してるみたい。現在どこまで最適化の実装が進んでいるのかわからないが、開発が止まっているような雰囲気がある。まぁソースを見りゃいいんだけど…

LLVM

LLVMのリンカは、普通に未使用関数の削除をしてくれた。

リンク時の最適化なんて、LLVMにとっては大した特徴ではないのかもしれないが、サイズが小さくなる事は良い事だ(サイズだけじゃないけど)。すばらしい。

LLVM Link-time optimization

 llvm-gcc --emit-llvm -c hoge1.c -o hoge1.o
 llvm-gcc --emit-llvm -c hoge2.c -o hoge2.o
 llvm-ld hoge1.c hoge2.c -o hoge
 llc hoge
 gcc hoge.s -o hogen

Diablo

リンク時最適化について調べていたら、Diablo(Diablo is a better link time optimizer)というリンク時最適化フレームワークを発見した。論文*1によると、ARMの場合は、ADSとGCCGCCbinutilsへのパッチが必要)に適用可能で、通常の10%程度サイズと速度面でのパフォーマンス向上が見られたとの事。試してみる価値はあるかもしれない。

GCC4系への対応があまり積極的に行われていない模様。というか、開発とまってんのか?

Diablo (Diablo is a better link time optimizer)

*1:Link-Time Optimization of ARM Binaries (2004) citeseerで検索しましょう!