SIMD 概論
前提知識: プログラミングの基礎知識。CPU アーキテクチャの概要があると望ましい。
このページの要点
- SIMD(Single Instruction, Multiple Data)は 1 つの命令で複数のデータを同時に処理する並列化手法である
- x86-64 では SSE2 が基本命令セットに含まれ、すべての 64 ビット CPU で 128 ビット SIMD が使える
- 将棋エンジンでは 9×9 = 81 マスのビットボード表現に 128 ビット SIMD が自然に適合する
- SIMD の恩恵を最大化するには、対象 CPU の命令セット対応状況を正しく把握する必要がある
SIMD とは何か
SIMD は Single Instruction, Multiple Data の略で、1 つの命令で複数のデータ要素を同時に処理するプロセッサの実行モデルです。 Flynn の分類1における 4 つの計算モデルの一つに位置づけられます。
| 分類 | 命令 | データ | 説明 |
|---|---|---|---|
| SISD | 単一 | 単一 | 従来型のスカラー処理 |
| SIMD | 単一 | 複数 | ベクトル演算・データ並列 |
| MISD | 複数 | 単一 | 実用例はほぼない |
| MIMD | 複数 | 複数 | マルチコア・分散処理 |
通常のスカラー命令では、1 つの加算命令は 1 組のオペランドしか処理できません。 SIMD では、たとえば 128 ビットレジスタに 4 つの 32 ビット整数を詰め込み、1 命令で 4 組の加算を同時に実行できます。
スカラー演算(SISD): A₁ + B₁ = C₁ ← 1命令で1組
SIMD 演算:
[A₁, A₂, A₃, A₄]
+ [B₁, B₂, B₃, B₄]
= [C₁, C₂, C₃, C₄] ← 1命令で4組
レジスタ幅とデータ並列性
SIMD の性能はレジスタ幅に大きく依存します。 レジスタが広いほど、1 命令で処理できるデータ量が増えます。
| レジスタ幅 | 命令セット例 | 64bit 要素数 | 32bit 要素数 |
|---|---|---|---|
| 64 bit | MMX | 1 | 2 |
| 128 bit | SSE2, NEON | 2 | 4 |
| 256 bit | AVX2 | 4 | 8 |
| 512 bit | AVX-512 | 8 | 16 |
ただし、レジスタ幅が広ければ常に速いとは限りません。 消費電力の増加によるクロックダウン(特に AVX-512)、アラインメント制約の厳格化、レジスタ間のデータ移動コストなど、幅を広げることによる副作用も存在します。
SIMD の 2 つの用途
SIMD は大きく分けて 2 つの文脈で使われます。
1. データ並列演算
画像処理・音声処理・科学計算など、同種のデータを大量に処理する場面です。 たとえば画像のピクセルごとの輝度補正では、128 ビット SSE2 レジスタに 16 個の 8 ビットピクセルを詰め込み、一括で演算します。 これが SIMD の最も典型的な用途です。
2. ワイドレジスタ演算
64 ビットを超えるデータを 1 つの単位として扱う用途です。 将棋のビットボードはこちらに該当します。 9×9 = 81 マスを表現するには 64 ビットでは不足するため、128 ビットレジスタを「1 つの大きな整数」として利用します。 AND・OR・XOR などの論理演算は、要素幅に関係なくビット単位で動作するため、128 ビット全体に対して 1 命令で適用できます。
ビットボードの OR 演算:
128bit: [先手の駒がいるマス] | [後手の駒がいるマス] = [全駒のいるマス]
→ SSE2: por xmm0, xmm1 ← たった1命令
なぜ将棋エンジンで SIMD が重要か
将棋エンジンにとって SIMD が重要な理由は 3 つあります。
理由 1: 81 マス問題
チェスは 8×8 = 64 マスなので、uint64_t 1 つでビットボードを表現できます。
将棋は 9×9 = 81 マスあり、64 ビットに収まりません。
128 ビット SIMD レジスタ(SSE2 の __m128i)を使えば、81 ビットを 1 つのレジスタに格納し、論理演算を 1 命令で実行できます。
rsshogi のビットボード実装の詳細は ビットボードのレイアウト を参照してください。
もし SIMD を使わなければ、[u64; 2] の各要素に対して個別に演算する必要があり、演算量が 2 倍になります。
特にビットボード演算は指し手生成の最内周ループで膨大な回数呼ばれるため、この差は大きく効きます。
理由 2: 頻出プリミティブの低コスト化
探索エンジンは局面更新・合法手生成・利き計算を大量に呼び出します。 rsshogi は探索本体を持ちませんが、これらの基盤処理を提供するため、ビットボード演算の SIMD 化は利用側エンジンの実行コストを下げる土台になります。
理由 3: NNUE 評価関数(探索エンジン側の話)
現代の将棋エンジンは NNUE(Efficiently Updatable Neural Network)による評価関数を使用します。 NNUE の差分更新や推論計算には大量のベクトル演算が含まれ、AVX2 や AVX-512 の恩恵が極めて大きい分野です。 Stockfish や 参照実装では NNUE 推論に AVX2 を積極的に活用しており、SSE2 のみの環境と比較して数倍の性能差が生じます。
注意: rsshogi は評価関数を含まない基盤ライブラリです。NNUE の実装は rsshogi を利用する探索エンジン側の責務です。 rsshogi が提供する SIMD 最適化(ビットボード演算・利き計算)は評価関数とは独立した機能です。
命令セット拡張の全体像
x86 / x86-64 プロセッサにおける主要な SIMD 関連の命令セット拡張を以下にまとめます。 各拡張の詳細な歴史と CPU 対応状況は「拡張命令の歴史」で、ビットボード処理で使う個別命令の解説は「拡張命令リファレンス」で扱います。
| 命令セット | 登場年 | レジスタ幅 | 主な用途(将棋エンジン視点) |
|---|---|---|---|
| MMX | 1997 | 64 bit | (現在は使用しない) |
| SSE | 1999 | 128 bit | 浮動小数点演算 |
| SSE2 | 2001 | 128 bit | ビットボード論理演算の基盤 |
| SSE3 | 2004 | 128 bit | 水平加算 |
| SSSE3 | 2006 | 128 bit | バイトシャッフル(byte_reverse) |
| SSE4.1 | 2007 | 128 bit | ゼロテスト(_mm_testz_si128) |
| SSE4.2 | 2008 | 128 bit | 文字列処理、CRC32 |
| POPCNT | 2008 | — | ビットカウント |
| AVX | 2011 | 256 bit | 浮動小数点 256 bit 演算 |
| BMI1 | 2013 | — | TZCNT, LZCNT, ANDN |
| BMI2 | 2013 | — | PEXT, PDEP |
| AVX2 | 2013 | 256 bit | 整数 256 bit 演算(角の並列処理等) |
| FMA3 | 2013 | — | 積和演算(探索エンジンの NNUE 等) |
| AVX-512 | 2017 | 512 bit | (探索エンジンの NNUE 推論等) |
太字は将棋エンジンで特に重要な命令セットです。
SIMD と将棋エンジンの関係図
┌─────────────────────────────────────────────────────┐ │ rsshogi(基盤ライブラリ) │ ├─────────────────────────────────────────────────────┤ │ ビットボード / 利き計算 / 合法手生成 │ │ (128 bit Bitboard / 256 bit Bitboard256) │ ├─────────────────────────────────────────────────────┤ │ SSE2 論理演算 │ SSSE3 シャッフル │ SSE4.1 テスト │ │ AVX2(角の 4 方向並列) │ ├─────────────────────────────────────────────────────┤ │ POPCNT │ BMI1 (TZCNT/LZCNT) │ BMI2 (PEXT/PDEP) │ │ ビット操作専用命令 │ └─────────────────────────────────────────────────────┘
※ NNUE 評価関数は rsshogi の範囲外。
探索エンジン側で AVX2 / AVX-512 / FMA3 等を活用して実装する。
非 x86 環境: ARM NEON
ARM アーキテクチャにも NEON と呼ばれる 128 ビット SIMD 拡張があります。 AArch64(64 ビット ARM)では NEON が必須仕様であり、すべての 64 ビット ARM プロセッサで利用可能です。
Apple Silicon(M1 以降)は NEON の性能が非常に高く、x86-64 の SSE2 と同等以上の性能を発揮します。 Raspberry Pi 4 以降や AWS Graviton なども AArch64 であり、NEON が使えます。
ただし、ARM には PEXT/PDEP に相当する命令がないため、BMI2 依存のアルゴリズムは利用できません。
POPCNT に相当する CNT 命令は存在します。
rsshogi の現状: ここで述べた NEON は一般的な背景であり、rsshogi の現在の実装には NEON 専用の コードパスはありません(
simd/u64x4/mod.rsに「AVX512/NEON は未導入」と明記)。AArch64 では 128bit 演算はスカラー実装にフォールバックします。SIMD で高速化されるのは AVX2 が有効な x86-64 環境です。
この章の構成
| ページ | 内容 |
|---|---|
| 拡張命令の歴史 | SSE から AVX-512 までの変遷、Intel/AMD の CPU 世代ごとの対応、非対応 CPU の情報 |
| 拡張命令リファレンス | ビットボード処理で使う個別命令の動作・用途・性能特性 |
-
Flynn, M. J. (1972). “Some Computer Organizations and Their Effectiveness”. IEEE Transactions on Computers, C-21(9), 948–960. ↩