画像の二値化を SIMD で高速化する

August 10th, 2010  |  Published in CS  |  1 Comment

SIMD の練習がてら、 ARM NEON で画像の二値化を SIMD 化してみる。

元コードは、 実践! iPhoneアプリ開発 : カメラアプリの作り方 (4) – 写真にエフェクトをかける で、 RGB から Y に変換するところと、 UIImage とビットマップとをやりとりするところを流用しています。

SIMD 化戦略は、単純なピクセル並列。 RGBA 各1バイトのピクセルを複数ピクセルまとめて処理するだけ。スケーリングとかのアルゴリズムと違って、近傍のピクセルを考慮しなくてよいので、端の処理も気にしないで済む。

RGB は1バイトなんだけれど、 Y に変換する際に 1バイトで表現できる以上の整数値を扱うことになるので、2バイトの整数で計算する。なので8ピクセルの SIMD にしたのが以下のコード:

まぁ分かりやすい。

iPhone 4、 -Os、 2592×1936 な JPG 画像で試したところ、

  • naive な実装 : 0.689s
  • NEON SIMD : 0.613s

と僅差で勝利した.. 詳しく追ってないけれど、最後のメモリ書き戻しのところが遅そう。

あとはこれを VFP でもやりたいんだけど、ちょっとめんどうげな。最初に RGB を float に変換してしまって、 4並列の SIMD でやることになるかな。果たして naive な実装に勝てるんだろうか.. GCC/Clang こわいです。


Tags: , parallel, SIMD
  • Neonoptimizer

    iPhone scheme関係を検索していたらたどり着きました。 変換して2値化はとりあえずSIMD化で4倍以上、ほかにも最適化(-Oではなく)したら10倍くらい見積もってもよいかと。 今回の場合、read/writeの書き方がnativeと変わらないので速度が出ていませんね。