Common lisp最適化基礎

4,410 views

Published on

Published in: Software
0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
4,410
On SlideShare
0
From Embeds
0
Number of Embeds
3,337
Actions
Shares
0
Downloads
8
Comments
0
Likes
3
Embeds 0
No embeds

No notes for slide

Common lisp最適化基礎

  1. 1. Common Lisp最適化基礎 TOYOZUMI Kouichi @TOYOZUMIKouichi FILMASSEMBLER
  2. 2. FILMASSEMBLER 2 今日話すこと 1. 最適化という言葉について 2. 計算機に対する最適化 3. Common Lispと最適化 4. これからのこと 5. ピクセルバイピクセルフィルタとmap-imageの実装 ・コード例はあくまで例です  ・実際に動かしてません  ・以前実装して試したことはあります ・ベンチマークは大変なので、いつかまとめてな感じで  ・(ヘタなこと言うと後々難しいので) はじめに
  3. 3. FILMASSEMBLER 3 おはなしする最適化の目的 ・最適化=最も適した状態にすること  ・「一体何に対して適しているのか」  ・「適することによる目的はなんなのか」 ・「速くすること」について話します  ・組み合わせ最適化とかそういう話じゃないです  ・速いとはどういうことか  ・例えばコンパイル時に計算終了は「速い」のか 少なくとも 大量の同格のデータを処理するときの全体で要する時間を短くする ことを目的とした話をします 最適化という言葉について
  4. 4. FILMASSEMBLER 4 おはなしする最適化の対象 ・「一体何に対して適しているのか」  ・問題に対する最適化   ・やりかたの話    ・もっと速いこんなアルゴリズムがあったんですよ  ・計算機に対する最適化   ・やりくりの話    ・この命令使うとこの処理がこんなに速くなるんですよ    ・こんな順番でやると速くなるんですよ    基本的に計算機に対する最適化、つまりやりくりの話をします 最適化という言葉について
  5. 5. FILMASSEMBLER 5 命令の総量を減らす ・反復の回数を削減する  ・「一度の反復でまとめてやればいいのに二度の反復でやった」   ・関数型プログラミングすると起きがち    ・mapやfilterの内部では反復が走っている    ・mapを連結すると何回も反復をやっている「かもしれない」  ・「反復の外でやればいいのに反復の中でやった」   ・意外に逃れづらいものがある ・余計な転送を減らす  ・スワップの回避はこれの代表例  ・「GPUに計算させたら逆に遅くなった」 計算機に対する最適化
  6. 6. FILMASSEMBLER 6 苦手な命令を減らす ・計算機には得手不得手がある  ・条件分岐がとても苦手   ・実体はいろいろあるけど今回は無視 ・目に見える条件分岐を減らす  ・ifの入れ子のうまい組み方をしたり、まとめてしまう   ・そんなに難しくないです ・目に見えない条件分岐を減らす  ・メモリの確保を減らす   ・空いているブロックを探索する処理は重い  ・ガーベジコレクションを減らす   ・時期を制御して都合のいいときにやらせる 計算機に対する最適化
  7. 7. FILMASSEMBLER 7 マルチパラダイムプログラミング言語と最適化 ・念のためですがCommon Lispはマルチパラダイム  ・いろんな言語のいいとこ取りでプログラミングできる  ・メモリ割り当てを減らすには手続的な破壊的操作が有効  ・遅延評価は動画像処理に便利です   ・「このフレームを返す関数」  ・そもそも動画の再生って継続だよね ・Paul Grahamがいうところの抽象度のスペクトルを自在に移動  ・簡単に書けるところは簡単に書いて、速くしたいところは凝る  ・巨大なコードでもチューニングが楽   ・1人で巨大で実用的なソフトウェアを書ける   ・お金なくてAfterEffectsが買えないから自作しようとした Common Lispと最適化
  8. 8. FILMASSEMBLER 8 最適化とマクロ ・速いコード=危ないコード  ・前回お話ししたとおり基本的にunsafe  ・ヘタするとトラップされない例外を吐く  ・最悪ldbのレベルに落ちて回復不可能に ・速いコード=長いコード  ・長くてわけがわからないコードになります  ・とても書きづらい どちらの問題も関数と 伝家の宝刀マクロが解決してくれます Common Lispと最適化
  9. 9. FILMASSEMBLER 9 マクロとコンパイラマクロ ・通常のマクロ  ・基本的にコードの簡略化担当   ・前回紹介したdefunsafeなんかがその例  ・「スワップ回避やガーベジコレクションの制御を含んだ構文」  ・「うまいifの組み合わせにしてくれる構文」 ・コンパイラマクロ  ・「反復の外でやればいいのに反復の中でやった」   ・コンパイラマクロを使った部分評価で回避できることもある 最大の利点は「処理系がやるような最適化」を自力で組めること 関数でラップすれば最適化の有効範囲を限定できるため バグの発生も少ない Common Lispと最適化
  10. 10. FILMASSEMBLER 10 許されるなら今日含めてたぶん三回はやります ・入門では道具の紹介 ・基礎では簡単な最適化  ・コンパイラマクロなし  ・マクロを使った独自構文の実装例 ・応用では基礎の内容から独自構文を隠  ・コンパイラマクロ使う  ・ちょっとした実行時(コンパイル時)コード生成 ・発展では「反復の外でやればいいのに反復の中でやった」への対応  ・より高度な実行時あるいはコンパイル時コード生成  ・コード生成の戦略 ・題材はMayaka https://github.com/TOYOZUMIKouichi/Mayaka/wiki  ・画像処理ライブラリだと思ってください これからのこと
  11. 11. FILMASSEMBLER 11 map-imageについて ・名前の通り「画像に対するmap」です ・「画素をとって画素を返す関数」と画像を渡すと画像を返します ・基本的な画像処理(ピクセルバイピクセルフィルタ)が書けます  ・階調反転  ・明るさ補正  ・モノクロ化 ・画像が二枚になると、合成処理が書けます ピクセルバイピクセルフィルタとmap-imageの実装
  12. 12. FILMASSEMBLER 12 愚直な実装 ・縦横二つのループを回す  ・条件分岐が多い ・引数となっている関数が副作用なし  ・毎回画素のためにメモリを確保しているが、すぐに捨てられる ピクセルバイピクセルフィルタとmap-imageの実装 (defunsafe map-image image ((image image) (function func)) (typed-let* (((size size) (image-size image)) ((fixnum width) (size-width size)) ((image result) (make-image :size size))) (loop for y fixnum from 0 below (size-height size) do (loop for x fixnum from 0 below width do (set-image-pixel image x y (funcall func (image-pixel image x y))))) result)) (s-map-image image (typed-lambda ((pixel pixel)) (make-pixel (- @ (pixel-red pixel)) (- @ (pixel-green pixel)) (- @ (pixel-blue pixel)) (pixel-alpha pixel))))
  13. 13. FILMASSEMBLER 13 基本的な措置 ・画素の配置を改めて、ループが一重で済むように ・引数に渡す関数を副作用ありに  ・「map-imageを使うときは副作用ありにしてね」  ・すごいめんどくさい ・そもそも画素に格納する意味あるのか?  ・使いもしない画素に成分値出し入れするのはもったいない ピクセルバイピクセルフィルタとmap-imageの実装 (defunsafe map-image image ((image image) (function func)) (typed-let1 image result (make-image :size (image-size image)) (loop for offset fixnum from 0 below (image-length image) do (set-image-pixel image offset (funcall func (image-pixel image offset)))) result)) (map-image image (typed-lambda ((pixel pixel)) (set-pixel-red pixel (- @ (pixel-red pixel))) (set-pixel-green pixel (- @ (pixel-green pixel))) (set-pixel-blue pixel (- @ (pixel-blue pixel))) pixel))
  14. 14. FILMASSEMBLER 14 転送量の削減 ・画素を渡すんじゃなくて成分値をそのまま渡す仕様に  ・画素の確保問題が解決  ・出し入れの問題が解決   ・レジスタ上で処理が終わるように ・引数の数がいきなり4倍に  ・めんどくさい  ・確かに語数は減ってるけど多値なので取り回しは悪い ピクセルバイピクセルフィルタとmap-imageの実装 (defunsafe map-image image ((function func) (image image)) (typed-let1 image result (make-image :size (image-size image)) (loop for offset fixnum from 0 below (image-length image) do (typed-multiple-value-bind ((component-t red green blue alpha)) (funcall func (image-components image offset)) (set-image-components image offset red green blue alpha))) result)) (map-image image (typed-lambda ((component-t red green blue alpha)) (values (- @ red) (- @ green) (- @ blue) alpha)))
  15. 15. FILMASSEMBLER 15 マクロによる隠 ・単純に画素と成分値なら展開できる  ・適当な構文を作って自動的に展開するように  ・画素用に関数を定義しているけど、接頭辞つければ成分値用 ・しかし問題がいくつか  ・独自の構文やお作法多くてめんどくさい  ・ほんとに全部展開できるの?失敗したら? ピクセルバイピクセルフィルタとmap-imageの実装 (defunsafe2 invert-pixel pixel ((pixel pixel)) (pixel (invert-component (pixel-red pixel)) (invert-component (pixel-green pixel)) (invert-component (pixel-blue pixel)) (pixel-alpha pixel))) (defunsafe2 c-invert-pixel (component-t component-t component-t component-t) ((component-t red green blue alpha)) (values (invert-component red) (invert-component green) (invert-component blue) alpha)) 展開
  16. 16. FILMASSEMBLER 16 とりあえずおしまい 1. 最適化という言葉について  ・大量の同格のデータを処理するときの全体で要する時間を短く  ・やりくりの話をする 2. 計算機に対する最適化  ・命令の総量を減らし、苦手な命令を減らす 3. Common Lispと最適化  ・マルチパラダイムプログラミング言語は大規模と最適化を両立  ・マクロを活用して高度な最適化を安全に隠 4. これからのこと  ・何回かに渡って順序を踏んで発表したい 5. ピクセルバイピクセルフィルタとmap-imageの実装  ・まずは愚直に実装し目についたことを直していく ご清聴ありがとうございました

×