SSブログ

MacOS Xの数値計算用API [プログラミング]

先日から始めたポリゴンレンダラの実行効率のいい実装のためにひさしぶりに調べ物をしている。MacOS Xで数値計算を実装するならAccelerateフレームワークを使うのが一番手っ取り早くて効率もいい。MacOS XではAccelerateフレームワーク以外にはFFTWgslがフリーであって、それ以外と言えばインテルのMKLと、NAGのポートぐらいだろう。Windowsではどうなんだろ。全然知らないんだけど、もっといい選択肢がいっぱいあるんだろうな。

MacOS XではAccelerateフレームワークは10.0から標準でインストールされるので使えるなら使ったほうがいい。またiOS6/MacOS X10.7からは完全に同じ呼び出しが両方のOSで使えるようになっている。

実はAccelerateフレームワークはいわゆるアンブレラフレームワークで、その中に
  • vDSP
  • vecLib
  • vImage
  • BLAS/CBLAS
  • LAPACK
が含まれている。LAPACKは言わずと知れた、超枯れた線形演算のパッケージで、これはすばらしいんだけどFORTRANで書かれていて、マトリクスはCとは転置した並びで与えないといけない。Cで書いてるとマトリクスのかけ算が左からではなく右からだと解釈すればいいようなものだけど、やっぱり混乱してバグの温床になりがちである。というか、ずっと昔CLAPACK(Cにf2cで変換されたLAPACK)を使おうとしてぐちゃぐちゃになって投げた苦い経験があるので、いまだにトラウマになっている。ちなみにWikipediaにはObjecttive-Cへのインターフェイスがあるように書いてあるが、これは間違い。そんなものはない。

BLAS/CBLASは低レベルのLPACK下請けライブラリだけど、これはAppleの手が入っていて効率化が図られているという(どの程度かは知らない)。それにLAPACKと違ってマトリクスを転置する必要はない(CBLASコールの中で転置が行われて結果が逆に転置されて格納されるようなスイッチを持っている)のでLAPACKにくらべればCからは使いやすいが、もちろん転置のオーバーヘッドは存在する。

vecLibはCPUのベクタユニットを使い倒すためのライブラリになっていて、さらにいくつかのサブライブラリに別れている。ベクタユニットを使うように拡張された数学関数や1024ビット長までの整数(binNum)の四則演算と論理演算が含まれている。vImageは画像処理に必要な痒い所に手が届く関数群がけっこうスマートにまとめられている。そしてvDSPは大きな配列のための単純計算の関数が膨大に用意されている。そしてvDSPには驚きのパフォーマンスを持ったFFTも含まれている。

vImageは10.4から、LAPACK/BLASは10.2から、それ以外は10.0から標準装備されていて、それなりに歴史がある。もちろん最初はPowerPCAltiVecに最適化されていたので、紆余曲折があってわかりにくいところも多く、とくにvDSPは整理されているとは言いがたい。

vDSPにはベクトルやマトリクスに対する四則演算などが大量に定義されている。ほとんどが単精度(float)と倍精度(double)の浮動小数点用の両方があって、一部複素数と、整数にも対応している。しかし例えばマトリクスどうしの積の関数はあるのに、ベクトルにマトリクスをかける関数がない。ふつうのアプリだとマトリクスどうしの積よりもマトリクスベクトル積のほうが出番が多いので、これは不思議。ひとつのマトリクスといろいろなベクトルをかけるときにはマトリクスどうしの積の形にできるのでそうしろ、というこのなのか。それともマトリクスに単一のベクトルをかけるだけではパフォーマンスを上げることができない、ということなのか。そのへんはよくわからない。

vecLibにはサブライブラリとしてvectorOpsというライブラリが含まれていて、それにはベクトルとマトリクスの積の関数が含まれているけど、これには単精度バージョンしかない。倍精度の場合のベクトルとマトリクスの積にはBLASを使え、ということなのか。それなら、そもそもvectorOpsは必要ない。なぜならBLASには単精度と倍精度の両方の関数が用意されていて、vectorOpsと機能がだぶっている。BLASのほうが引数が多くてずっと使いにくいけど。

MacOS Xの最初のプラットフォームだったPowerPCのAltiVecは、128ビット長のレジスタなので倍精度浮動小数点は2個入るんだけどサポートされていない。それは
  • 倍精度ではスカラユニットに較べて最大で倍の効率にしかならず、メモリアクセスが律速するとその差はさらに縮まる
  • なのに倍精度のためには単精度の何倍かの回路規模が必要になる
  • PowerPCは小さなチップ面積で実行効率が高いことがウリだったのでメリットが相殺される
  • 音声画像といったデータは単精度で十分
といったことからベクタユニットでは倍精度を割り切ったのだろうと思われる。

AccelerateフレームワークはまずAltiVecに最適化されたので、浮動小数点は単精度だけを対象にしていた。その後Intelに移植されてそのベクタユニットは倍精度も扱えた(SSE2から。Intelにとってチップ面積増大はPowerPCに較べれば問題としては軽い)ので、Accelerateフレームワークも部分的に拡張された。そういった歴史が反映しているのだろうと思われる。

しかし、どうも見通しが悪くて使いにくいんだよなあ、まったく。もっと整理してくれないかなあ。低レベルの配列演算はvDSPとBLAS/CBLASに集約してvectorOpsはobsoleteにすべきだなあ。vectorOpsはAltiVec臭くて抽象化のレベルがvDSPにくらべて低い。vDSPもぐちゃぐちゃなので、汎用と特定用途(サウンド関連と画像処理関連)は分けて汎用のほうはBLAS/CBLASとのアンブレラにした方がわかりやすいなあ。それと、LAPACKは残すにしても、もう少し使いやすい高レベルのルーチンが欲しいなあ。NAGはなんだか威丈高で雰囲気悪いし(これは個人的な感想です)めちゃ高い(費用が)ので、gslをAppleがサポートして標準装備してくれないかなあ。
nice!(0)  コメント(0)  トラックバック(0) 

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 0