Happy My Life

日常とか技術とか

インラインアセンブラの傾向と対策

iPhoneでインラインアセンブラを使う(資料編) - 強火で進め

やっぱり使えるのね、というのが最初の感想。以前のGCCならツッコミどころ満載のコードを吐いていたのでインラインアセンブラで書く価値は十分にあったけど、今はけっこう賢いコードを吐くようになったみたい。

個人的にはアセンブラで書くのは最終手段であって、最適化したけりゃ「コンパイラが吐くアセンブラコードを想定してCでゴリゴリ書いておけ」と思っている。書く時間がかかる割にはあまり高速化されないし、保守性が落ちるからってのがその理由。

ある程度プログラミング経験がある人は「アセンブラで書けは必ず高速化される」ようなイメージも持っている人も多そうだけど、今はCPUの特性(パイプライン、キャッシュ、分岐予測等)を熟知して書かないと逆に遅くなってしまう事も十分にありえる、そんな時代なのですよと。

それでもアセンブラで書きたい人へ

とはいえ技術的な好奇心を満たす為にアセンブラで書きたい人も多い気がするので、アセンブラコードを書く以前にすべき事を書いてみた。

完璧なデバック

アセンブラで高速化した領域が実はバグ有りって事なら目も当てられません。

関数の時間計測

やみくもにアセンブラで書いても高速化されないし、たまにしか実行されない所をアセンブラで書いても高速化されない。ので、まずプロファイラというツールを使い、どの関数が一番処理時間がかかっているかを把握するのが一番先。パレートの法則 - Wikipediaがここでも生きるわけ。

あと、勘で「たぶんこの関数が重い」という先入観は捨てる事。間違っている事多いから。

CPU特性の熟知

1命令は何バイト? キャッシュエリアは何キロバイト? レジスタはいくつある? 命令体系はどんな感じ?などなど、普通は知っていてもムダだけど高速化するには必須の知識。ただアセンブラで書きたいってだけなら、レジスタと命令体系だけ知っておけばいいんだけどね。

CPU特性にあわせたアルゴリズムの変更

ここからが腕の見せどころ。アルゴリズムの変更で重要なのは

  • できる限りキャッシュにヒットさせる
  • できる限りキャッシュにヒットさせる
  • できる限りキャッシュにヒットさせる

大切な事なので3回言いました。メモリアクセスも最低限に抑える事。そのためには、キャッシュとレジスタで極力やりくりする。これが一番大事。アルゴリズム早くてもメモリアクセスやキャッシュにヒットしなかった為にメモリアクセスが発生して遅くなる、という事も十分考えられるわけで。

アセンブラで書くだけで高速化される時代は既に終った

複雑怪奇になった各種CPUの世界を堪能してくださいw