今回はベクトル演算、SIMD演算の話です。ベクトル演算とSIMD演算は並列計算としては同種の高速化で、配列計算の一括処理です。マルチコアとは別の概念ですが、重要な並列技術ですのでこのブログでも取り上げたいと思います。画像処理やAI処理の高速省エネルギー実行に重要な技術であり最近話題のNPU (Neural Processing Unit)などにも使われています。NVIDIA社のGPGPUはマルチコアとSIMDとの中間的な技術ですが、同様に配列計算の一括処理であり、関連技術として次の機会に紹介します。
SIMDとはSingle-Instruction-Multiple-Dataの略で、複数のデータを同一の命令で処理するという意味です。通常のプロセッサの演算は下図の左の加算のように1組の数を足して1個の結果を得ますが、ベクトル演算やSIMD演算は、同時に複数組(図の例では4組)の数を足して複数個(図の例では4個)の結果を得るような処理です。なお、演算の名称はハードウェアベンダが名付けるものであり、学術的な定義はありません。歴史的にSIMD演算はIntelのSSEのように例えば4並列を1~数サイクル程度で実行するもの、ベクトル演算器はRISC-Vのベクトル拡張のように例えば64並列を数~10サイクル程度で実行するものに使われることが多いようです。
同時に演算するためにはベクトル演算器(SIMD演算器)の存在が前提です。ここで、少し専門的にはなりますが、下の図のSIMD演算器の例を用いて通常のプロセッサの演算との違いについて説明します。
左図が通常のプロセッサの例であり、レジスタとよばれるデータ格納場所からデータを2個読み、演算実行後、結果をレジスタに保持します。図の例は、レジスタR2とR1に格納されているデータを加算し、レジスタR3に保持します。この動作は、例えば図の中のアセンブリ言語命令 add R3, R2, R1 のような命令に対応する機械語命令により実行されます。
これに対して右図がSIMD演算器の例です。複数の値を保持できるSIMDレジスタを持ち、複数の演算器を用いて同時に演算を実行します。図の例では、データを4個ずつ保持できるSIMDレジスタが存在し、SIMDレジスタVR2とVR1に格納されているデータを加算し、SIMDレジスタVR3に保持します。この動作も機械語命令により実行されます。例えば図の中のアセンブリ言語命令 simdadd VR3, VR2, VR1 のような命令に対応する機械語により並列実行します。
ベクトル演算(SIMD演算)を高速に実行するためには、演算器が複数存在することと、ベクトル(SIMD)レジスタから演算器を通りベクトル(SIMD)レジスタに戻るデータ転送経路が高い性能を持つことが必要です。実際にハードウェア実装により高速処理が可能になっているのが一般的で、ソフトウェアからみたときのオーバーヘッドは極めて小さいですが、ハードウェア面積の制約がありますので同時実行並列数には制限があります。そのため、並列数が多くなるとマルチコアとの併用が必要となってきます。このことについては次の機会に説明します。
演算器の名称には歴史的に傾向があることは前述したとおりです。SIMD演算は、128bitのSIMDレジスタを32bit×4個に分割して用いるIntelのSSEのように、データ数が比較的少なく固定長の場合、ベクトル演算器は、RISC-Vのベクトル拡張のように32bit×64個のように比較的データ数が多く可変長にも定義できる場合に使われることが多いようです。この意味で考えた場合、SIMD演算器はCPUコアの中に組込まれ、データ転送や加算のような簡単な計算であれば1サイクルで実行可能に設計・実装可能になります。
レジスタが保持するデータ数を多くし、演算器数も多くすると、同時処理可能なデータ数を増加させることができますが、ハードウェア面積が大きくなるためCPUコアとは別のハードウェアモジュールとして設計・実装され、データ転送オーバーヘッドを考慮する必要がでてきます。これが上述の意味でのベクトル演算器であり、64個のデータ転送や加算のような簡単な計算を数~10サイクル程度で実現するような実装となります。可変長の場合、実装されているハードウェアよりも多く定義できる場合もありますが、その場合には内部で複数回に分けて実行されるので、それだけ長い計算時間を要します。
コメントをお書きください