SIMDとSIMTの違い:実行モデル・プログラミング・分岐・メモリアクセスを比較

SIMDもSIMTも、1つの命令で多くのデータに同じ演算をする点は同じですが、プログラムからの見え方が違います。SIMDはCPUのベクトル命令で、プログラマやコンパイラが幅の決まったベクトルレジスタにデータを並べ、明示的に命令を使います。SIMTはGPUの方式で、1本のスレッドの処理を普通に書くと、ハードウェアが32本などのスレッドをワープに束ねて同じ命令で動かします。スレッドごとに分岐も書けますが、ワープの中で分岐が分かれると両方の経路を順に実行するので、効率が下がります。

項目SIMDSIMT
実行モデル1つの命令で、ベクトルレジスタに並べた複数の要素を同時に処理する1つの命令を、ワープに束ねた多数のスレッドが同時に実行する。各スレッドは自分のレジスタを持つ
プログラムの見え方ベクトルの幅を意識して書く。組み込み関数、アセンブリ、コンパイラの自動ベクトル化を使う1本のスレッドの処理をスカラのコードとして書く。束ねるのはハードウェア
並列の幅レジスタの幅で決まる。例: 512ビットなら32ビットの数16個ワープの幅(32本など)。チップ全体では数万本のスレッドを同時に保持する
分岐の扱い要素ごとの分岐は書けない。比較結果のマスクで両方を計算して選ぶスレッドごとに書ける。ワープ内で分かれると両方の経路を順に実行し、該当しないスレッドを休ませる(ダイバージェンス)
有効な要素の管理プログラマやコンパイラが、マスク付き命令やブレンド命令で明示するハードウェアが、有効なスレッドを自動で管理する
メモリアクセス連続した番地をまとめて読むのが得意。ばらばらの番地はギャザー・スキャッタ命令で扱うが遅い各スレッドが自由に番地を指定できる。隣り合うスレッドが隣り合う番地を読むとまとめられる(コアレッシング)
メモリの遅延の隠し方大きなキャッシュ、アウトオブオーダー実行、プリフェッチ多数のワープを切り替え、待っているワープの間に別のワープを動かす
フリンの分類での位置づけSIMDそのものSIMDの一種を、スレッドの形で見せる方式
代表的な使われ方CPUのベクトル命令。画像・音声の処理、暗号、行列演算のループなどGPUのワープ。グラフィックス、AIの学習・推論、科学技術計算などの大規模な並列計算

数値は代表的な目安で、世代や製品によって異なります。

どんなときに使うか

SIMD
CPUの上で、配列の要素ごとに同じ計算をするループを速くしたいとき。データが連続して並び、繰り返しの間に依存がないと効果が大きく、コンパイラの自動ベクトル化でも使えます。
SIMT
数千〜数百万の独立した要素に同じ処理をする大規模な並列計算。GPUで、スレッドごとのプログラムを書いて実行します。ワープの中で分岐とメモリの番地がそろうように作ると効率が上がります。
組み合わせ
GPUの中では、ワープを単位としたSIMTの実行がSIMDの演算器の上で行われます。CPUとGPUを一緒に使うシステムでは、前処理や制御をCPUのSIMDで、大きな並列計算をGPUで分担します。

よくある質問

SIMTは、SIMDとまったく別の仕組みなのですか?

ハードウェアの中では近い仕組みです。ワープの各スレッドはSIMDの演算器の1つのレーンに対応し、同じ命令で動きます。違いは見せ方で、SIMTではスレッドごとのレジスタ、番地、分岐をハードウェアが扱うので、プログラマはベクトルの幅を意識せずに書けます。

ワープダイバージェンスを減らすにはどうすればよいですか?

同じワープのスレッドが、なるべく同じ側の分岐を通るようにします。例えば、条件の結果がそろうようにデータを並べ替える、ワープの単位で条件が切り替わるようにスレッドの番号を割り当てる、短い分岐は選択の演算に置き換える、などの方法があります。

SIMDで、if文のある処理はどう書くのですか?

比較命令で要素ごとの条件をマスクにし、両方の結果を計算したうえで、マスクに従って要素ごとに選びます。マスク付きの命令がある命令セットでは、条件を満たす要素だけを演算・格納できます。両方の経路を計算するので、分岐の中身が重いと効率が下がる点は、SIMTのダイバージェンスと似ています。

コンパイラの自動ベクトル化がうまくいかないのは、どんなときですか?

繰り返しの間に依存があるとき(前の結果を次で使うとき)、ポインタが同じ領域を指している可能性があるとき、データが連続して並んでいないとき、ループの中に複雑な分岐や関数の呼び出しがあるときなどです。依存がないことをコンパイラに伝える指定や、データの並べ方の変更で、ベクトル化できる場合があります。

理解度チェック

1つの命令で複数のデータに同じ演算を同時に行う方式はどれか。

  1. ASISD
  2. BSIMD
  3. CMISD
答えと解説を見る

正解:B. SIMD

SIMDは、1つの命令で複数のデータに同じ演算を並列に行う方式で、例えば512ビットのレジスタなら32ビットの数値16個を一度に計算できます。x86のSSE・AVX、ARMのNEON・SVEなどがあり、画像処理、動画の圧縮、行列演算などで数倍以上の高速化が得られます。フリンの分類ではほかにSISD(通常の逐次処理)、MIMD(マルチコア)などがあります。

NVIDIAのGPUで、32本のスレッドを1つの束にして、同じ命令を一斉に実行する単位を何と呼ぶか。

  1. Aワープ
  2. Bグリッド
  3. Cページ
答えと解説を見る

正解:A. ワープ

ブロックの中のスレッドは、ハードウェアの中では32本ずつのワープに分けられ、1つのワープの32本は同じ命令を同時に別々のデータに対して実行します。このように、スレッドとして書いたプログラムを束にして同じ命令で動かす方式をSIMTと呼びます。AMDのGPUでは同じような単位をウェーブフロントと呼び、64本または32本です。ブロックの大きさは32の倍数にするのが基本です。

GPUのSIMT(単一命令・複数スレッド)の方式と、CPUのSIMD命令の違いとして正しいものはどれか。

  1. ASIMTは1つのデータに複数の命令を同時に行い、SIMDは1つの命令を1つのデータに行う
  2. BSIMTとSIMDはまったく同じもので、名前が違うだけである
  3. CSIMTでは各スレッドを独立したプログラムとして書け、分岐もハードウェアが処理するが、SIMDではプログラマやコンパイラが幅の決まったベクトルの命令を明示的に使う
答えと解説を見る

正解:C. SIMTでは各スレッドを独立したプログラムとして書け、分岐もハードウェアが処理するが、SIMDではプログラマやコンパイラが幅の決まったベクトルの命令を明示的に使う

CPUのSIMDでは、4個や8個のデータをまとめたベクトルのレジスタに1つの命令をかけるので、プログラムはベクトルの幅を意識して書きます。GPUのSIMTでは、プログラマは1本のスレッドの処理を普通に書き、ハードウェアが32本ずつ束ねて同じ命令で動かします。スレッドごとに分岐してもよく、ハードウェアが分岐した経路を順に実行しますが、そのときは効率が下がります。

  1. 1つのワープの中で、条件分岐によってスレッドの半分がif側、残りの半分がelse側に分かれた(ワープダイバージェンス)。一般にどう実行されるか。
  2. GPUのメモリ合体アクセス(コアレッシング)の説明として正しいものはどれか。
  3. コンパイラの自動ベクトル化で使われる命令の種類として正しいものはどれか。

GPUプログラミングの練習問題へ

関連する用語の解説

SIMD
Single Instruction, Multiple Data の略。1つの命令で複数のデータに同じ演算を同時に行う方式。画像処理やAIの計算を高速化する。
SIMT
単一命令・複数スレッドの方式。プログラムはスレッドごとに書くが、ハードウェアはワープ(NVIDIAでは32本)ごとにスレッドを束ねて同じ命令で実行する。
ワープダイバージェンス
1つのワープの中で条件分岐によりスレッドの進む道が分かれること。分かれた道を順に実行するので効率が下がる。
メモリコアレッシング
ワープの中の隣り合うスレッドが隣り合う番地にアクセスしたとき、まとめて少ない回数のメモリアクセスにすること。合体アクセス。
ベクトル化
ループの中で要素ごとに行う同じ計算を、SIMD命令を使って複数の要素にまとめて行う形に変える最適化。繰り返しの間にデータの依存がないことが条件になる。

関連する比較