7
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

OpenCVAdvent Calendar 2024

Day 9

可変ベクトル長に合わせたSIMD実装はより素敵です

Last updated at Posted at 2024-12-08

この記事はOpenCV Advent Calendar 2024の9日目の記事です。
他の記事は目次にまとめられています。

TL;DR

  • 今どきのSIMDは、ベクトル長が可変であることも少なくない
  • これからのSIMD実装は、可変ベクトル長対応し、「ものすごいCPU」でも「そこそこCPU」 でも大丈夫なように作りましょう!

はじめに

@tomoaki_teshima先生の2022年投稿がこちらの「OpenCV の dispatch機能について」でございます。

そういえば、WAYLAND対応の時にRAW RGBに変換するべくSIMD実装検討もしたなあ、ということで、今どきのSIMDの書き方をまとめておきたい。もし、SIMD実装しなきゃいけなくなったときに思い出していただけますと幸いです。

SIMD技術の今昔

(ものすごくざっくりです)MMXとかSSEとかのSIMD創世記は、ベクトル長が非常に重要でした。64bit, 128bit, 256bit .... 大きければ大きいほどまとめて処理できる=性能アップ。ただ、常に使うわけでもないし、新しい技術を導入すると後方互換性がなくなる、となかなか悩ましい問題でございました。

CPU Tech Vec Len
x86 MMX 64bit
x86 SSE 128bit
x86 AVX 256bit
x86 AVX-512 512bit
ARM NEON 64bit / 128bit

しかも最近は、消費電力削減のために、複数種類のCPUを合わせたヘテロジニアウスな構成も出てきている。
その中で、人類は気が付いたのです。「更なる自由を!」

ARMのScalable Vector Extension(SVE)やRISC-VのVector Extensionは、ベクトル長が可変となっている。つまり、一般普及用の短いベクトル長のCPUでも、High performance computing用の長いベクトル長のCPUでも、同じ命令が処置できる!!

つまり
(1)Intel CPUでいえば、AVX-512対応しているP-coreでも、AVX2どまりのE-coreでも。
(2)ARM CPUでいえば、BIG(Cortex-A725)でもlittle(Cortex-A520)でも。
どちらでも、同じ命令が実行できるということでございまする!!これは素敵でございますねえ!!!

CPU Tech Vec Len
x86 AVX10.2 128, 256, 512
ARM SVE/SVE2 128~2048
RISC-V Vector Extension 32~2^16

今どきではないSIMD実装の書き方(SIMDベタ書き)

まずは、ベタ書きパターンを見ていく。

  • CV_SIMD128やCV_SIMD256を使ってコードブロックを制御
  • 変数の型(v_uint16x16とc_uint16x8)が混在し、超絶、読みにくい
  • 新しいSIMD技術がでると作り直しが必要
                    /* Update corresponding histogram segment */
#if CV_SIMD256
                    v_uint16x16 v_fine;
#elif CV_SIMD128
                    v_uint16x8 v_finel;
                    v_uint16x8 v_fineh;
#endif
                    if ( luc[k] <= j-r )
                    {
#if CV_SIMD256
                        v_fine = v256_setzero_u16();
#elif CV_SIMD128
                        v_finel = v_setzero_u16();
                        v_fineh = v_setzero_u16();
#else
                        memset(&H.fine[k], 0, 16 * sizeof(HT));
#endif
                        px = h_fine + 16 * (n*(16 * c + k) + j - r);
                        for (luc[k] = HT(j - r); luc[k] < MIN(j + r + 1, n); ++luc[k], px += 16)
                        {
#if CV_SIMD256
                            v_fine = v_add(v_fine, v256_load(px));
#elif CV_SIMD128
                            v_finel = v_add(v_finel, v_load(px));
                            v_fineh = v_add(v_fineh, v_load(px + 8));
#else
                            for (int ind = 0; ind < 16; ++ind)
                                H.fine[k][ind] += px[ind];
#endif
                        }

今どきのSIMD実装

それでは、レーンを使った「今どきのSIMD実装」も確認しておく。

  • VTraits::vlanes();で、レーン数(まとめて処理できるデータ件数)を取得
  • 変数の型(=ベクトル長)を気にせずに実装でき、非常に読みやすい
  • よりベクトル長が大きくなっても、コード修正なしで対応できる(厳密にはCMakefile修正は必要)
        src += cn; dst += cn;
        int i = cn, lencn = (len - 1)*cn;
#if (CV_SIMD || CV_SIMD_SCALABLE)
        const uint16_t* _m = (const uint16_t*)m;
        const int VECSZ = VTraits<v_uint16>::vlanes();
        v_uint16 v_mul0 = vx_setall_u16(_m[0]);
        v_uint16 v_mul1 = vx_setall_u16(_m[1]);
        for (; i <= lencn - VECSZ; i += VECSZ, src += VECSZ, dst += VECSZ)
            v_store((uint16_t*)dst, v_add(v_mul(v_add(  vx_load_expand(src - cn), vx_load_expand(src + cn)),  v_mul0), v_mul(vx_load_expand(src), v_mul1)));
#endif
        for (; i < lencn; i++, src++, dst++)
            *((uint16_t*)dst) = saturate_cast<uint16_t>(((uint16_t*)m)[1] * (uint32_t)(src[0]) + ((uint16_t*)m)[0] * ((uint32_t)(src[-cn]) + (uint32_t)(src[cn])));

まとめ

SIMD技術はこれからもベクトル長が大きくなる方向で進化していくと考えられる。

そうした場合に、それぞれのベクトル長ごとに実装するなんて、面倒くさい!

これからは、可変ベクトル長さのSIMD技術を使いこなしましょう!ということでまとめさせていただきます。

ご精読、ありがとうございました!

7
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?