ポリゴンレンダラ - その8 [プログラミング]
前回ポリゴンの集合に対して輪郭線を引く方法を考えた。今回の僕の最終的な目的のためには計算が素早くできないといけない。ひとまわりの計算がディスプレイのリフレッシュの間に終わることが望ましい。
ということで、今日は何を計算するかをまとめて、ちょっと実装に先回りして効率のいい計算のためにvDSPを使うことを考えてみる。
vDSPと言えばFFTなんだけど、それ以外の関数もたくさん含まれている。それでどんなことができるのか見通しがよくないので簡単に整理した表を作った。表になにが書いてあるかは続きを読んで欲しい。
それに、ベクタユニットを使いたくなるようなアプリケーションはたいていの場合、データがCPUのキャッシュにおさまりきらないぐらい大きい。したがって結局メモリアクセスが律速する、ということになる。
とはいうものの、せっかくあるので使わないのはもったいない。最近のコンパイラはベクタユットも含めて最適するようになっているし、MacOS XにはAccelerateフレームワークがあってベクタユニットに最適化(ものによって、だけど)されている。
また、新しいコンパイラはベクタユニットを使うようなコードも出力できるようになってきている。ヘタにvDSPなんか使ったせいでかえって遅くなる、なんてこともあり得る。
ということで、今回描画の効率を上げたいのでAccelerateフレームワーク、とくにvDSPを試してみる。
vDSPにはいろいろな、というより雑多な関数がごちゃごちゃとある。なかなか全体像がつかめないが、ざっくり言って
stride_1とstride_2は二つの配列のストライドを渡す。vDSPの関数があつかう配列は、詰まっている必要は無い。つまり例えば一つおきにならんでいてもいい。いくつ間が空いているかというのをストライドと呼ぶ。ストライドが1というのは密に詰まっている、ストライドが2だと一つおきにある、ということを表している。結果の配列のストライドはstrideResultという引数で渡す。
vDSPではかならず配列は
ほとんどの関数は単精度浮動小数点と倍精度浮動小数点に対応する両方の関数が用意されている。そのうちいくつかは複素数用もある。また、ごくたまに32ビット整数用がある。複素数は、必ず実数部と虚数部が別配列になったSplit型複素数にのみ対応する。
vDSPにあるFFT関連はReferenceをみればだいたいわかるが、単純計算の関数は、なにがあってなにがないのかわからないぐらいたくさんある。そこで関数の表(csvファイル)を作った。FFT関連以外の関数を網羅した。
表には
配列の型は
で示した。
関数名は型による修飾文字がついている。ここに書いた関数名をfuncとすると
などとなっている。かならず頭にvDSP_がくる。
関数の機能が式で表しやすいものは、LaTeXの形式で式を書いてある。書くまでもないもの(単純コピー関数など)や、式で書きにくいものには書いていない。その場合は機能の詳細説明のところに言葉で書いてある。言葉で書きにくい場合はなんとか式で書くようにして、すくなくともどちらかの説明があるようにしてある。
AppleのvDSP referenceは整理されないまま関数が追加されている(記述がダブってるのもある)ので、見通しが悪い。あらためて分類し直した。わかりやすい分類法があまりないので、若干恣意的に
vDSPのこういった関数群は、目的があって作られた訳ではなく、どちらかといえばベクタユニットがこういう使い方をすればこういう方面に使えるかもしれない、というシーズ側からの提案になっているせいで雑多なものになっているという気がする。
従って使う方は、目的にあったものを探し出すということができないといけない。そのためにはどんな関数があるのかわかってないといけない。そのためにこういう表はちょっとは役に立つかもしれない、と思って公開することにする。
ということで、今日は何を計算するかをまとめて、ちょっと実装に先回りして効率のいい計算のためにvDSPを使うことを考えてみる。
vDSPと言えばFFTなんだけど、それ以外の関数もたくさん含まれている。それでどんなことができるのか見通しがよくないので簡単に整理した表を作った。表になにが書いてあるかは続きを読んで欲しい。
6 計算のまとめ
なにを計算するのかをざっくりまとめると- 同次座標を使った座標変換
- 反射光の計算
- 輪郭線の描画
- ポリゴンの座標と面の色(とPhong係数)が与えられる
- ポリゴンの法線を求めておく
- 視点の位置を決める
- ポリゴンの座標を平面の上に射影する
- 奥行き値によるポリゴンのソートを行う
- 光源-ポリゴン-視点の位置関係を調べる
- 反射の色を計算する
- ポリゴンを描画する
- そのとき法線ベクトルと視線ベクトルとの内積を計算し、隣りと符号が逆なら輪郭線を引く
7 計算の効率化
こういう単純な数値計算のために最近のCPUにはベクタユニットが備わっているものが多い。多くのベクタユニットは複数のデータを同時に(たいていの場合1クロックで)処理できる。と言ってもいっぺんに処理できるビット幅はせいぜい128ビット長で、倍精度浮動小数点なら2個ずつしか並列に処理できないのでスパコンのようなものではない。それに、ベクタユニットを使いたくなるようなアプリケーションはたいていの場合、データがCPUのキャッシュにおさまりきらないぐらい大きい。したがって結局メモリアクセスが律速する、ということになる。
とはいうものの、せっかくあるので使わないのはもったいない。最近のコンパイラはベクタユットも含めて最適するようになっているし、MacOS XにはAccelerateフレームワークがあってベクタユニットに最適化(ものによって、だけど)されている。
また、新しいコンパイラはベクタユニットを使うようなコードも出力できるようになってきている。ヘタにvDSPなんか使ったせいでかえって遅くなる、なんてこともあり得る。
ということで、今回描画の効率を上げたいのでAccelerateフレームワーク、とくにvDSPを試してみる。
vDSPにはいろいろな、というより雑多な関数がごちゃごちゃとある。なかなか全体像がつかめないが、ざっくり言って
- 配列(1次元、2次元)に対する四則演算やその他の単純演算
- FFTとそれを使った畳み込みなど
7.1 vDSPの関数
vDSPは呼び出し方が統一されている。例えば二つの配列の要素同士をかけ算する関数のプロトタイプがvDSP programming Guideにある。void vDSP_vmul( float *input_1, /* input vector 1 */ SInt32 stride_1, /* address stride for input vector 1 */ float *input_2, /* input vector 2 */ SInt32 stride_2, /* address stride for input vector 2 */ float *result, /* output vector */ SInt32 strideResult, /* address stride for output vector */ UInt32 size /* real output count */ );これは単精度浮動小数点数の配列へのポインタを3つわたす。input_1とinput_2という配列にかけ算する数値が並んでいて、その結果がresultという配列に格納されて返ってくる。それぞれの配列の長さは最後の引数のsizeでわたす。入力用の配列は破壊されないが、結果を格納する配列は前もって領域を確保しておく必要がある。ほとんどのvDSP関数は入力を破壊しないが、ほんのいくつかの例外がある。
stride_1とstride_2は二つの配列のストライドを渡す。vDSPの関数があつかう配列は、詰まっている必要は無い。つまり例えば一つおきにならんでいてもいい。いくつ間が空いているかというのをストライドと呼ぶ。ストライドが1というのは密に詰まっている、ストライドが2だと一つおきにある、ということを表している。結果の配列のストライドはstrideResultという引数で渡す。
vDSPではかならず配列は
- 先頭へのポインタ
- 長さ
- ストライド
ほとんどの関数は単精度浮動小数点と倍精度浮動小数点に対応する両方の関数が用意されている。そのうちいくつかは複素数用もある。また、ごくたまに32ビット整数用がある。複素数は、必ず実数部と虚数部が別配列になったSplit型複素数にのみ対応する。
vDSPにあるFFT関連はReferenceをみればだいたいわかるが、単純計算の関数は、なにがあってなにがないのかわからないぐらいたくさんある。そこで関数の表(csvファイル)を作った。FFT関連以外の関数を網羅した。
表には
- タイトル代わりの機能の簡単な説明
- 関数名
- 配列の型
- 機能を式で表現(可能な場合)
- 機能の詳細説明
- 引数宣言のかたち
配列の型は
f: | 単精度浮動小数点 |
D: | 倍精度浮動小数点 |
zf: | 単精度浮動小数点複素数 |
zD: | 倍精度浮動小数点複素数 |
i: | 32ビット整数 |
その他: | 1.15固定小数点、8.24固定小数点など特殊なのもの |
関数名は型による修飾文字がついている。ここに書いた関数名をfuncとすると
vDSP_func | 単精度浮動小数点用 |
vDSP_funD | 倍精度浮動小数点用 |
vDSP_funi | 32ビット整数用 |
vDSP_zfunc | 単精度浮動小数点複素数用 |
vDSP_zfunD | 倍精度浮動小数点複素数用 |
関数の機能が式で表しやすいものは、LaTeXの形式で式を書いてある。書くまでもないもの(単純コピー関数など)や、式で書きにくいものには書いていない。その場合は機能の詳細説明のところに言葉で書いてある。言葉で書きにくい場合はなんとか式で書くようにして、すくなくともどちらかの説明があるようにしてある。
AppleのvDSP referenceは整理されないまま関数が追加されている(記述がダブってるのもある)ので、見通しが悪い。あらためて分類し直した。わかりやすい分類法があまりないので、若干恣意的に
- もっとも簡単なもの
- 単純コピーなど
- 一つの配列に対して一つのスカラを出力するもの
- 平均値など
- 配列の生成
- 単純代入
- ランプ関数生成
- 変換
- 精度変換
- デカルト極座標変換
- デシベル変換
- 配列の四則演算
- ベクトルとスカラ
- ベクトルとベクトル
- 内積
- 非線形演算
- 大小判別
- 最大値最小値
- クリピングなど
- その他
- ソート
- 数値積分
- オートスペクトラム
- 行列演算
vDSPのこういった関数群は、目的があって作られた訳ではなく、どちらかといえばベクタユニットがこういう使い方をすればこういう方面に使えるかもしれない、というシーズ側からの提案になっているせいで雑多なものになっているという気がする。
従って使う方は、目的にあったものを探し出すということができないといけない。そのためにはどんな関数があるのかわかってないといけない。そのためにこういう表はちょっとは役に立つかもしれない、と思って公開することにする。
2013-04-22 21:36
nice!(0)
コメント(0)
トラックバック(0)
コメント 0