解答17: SIMD基礎

概要

ZigのSIMD(Single Instruction Multiple Data)機能を使って、ベクトル演算、配列演算、画像処理、行列演算の高速化について学びます。

解答のポイント

1. @Vector型

const v: @Vector(4, f32) = .{ 1, 2, 3, 4 };
const result = v + v;  // 要素ごとに加算

2. @reduce

const sum = @reduce(.Add, vector);  // 全要素の合計
const max = @reduce(.Max, vector);  // 最大値

3. @splat

const ones: @Vector(4, f32) = @splat(1.0);  // 全要素を1.0に

4. 配列とベクトルの変換

const vec: @Vector(4, f32) = array[i..][0..4].*;
array[i..][0..4].* = vec;

実装例: 配列加算のSIMD化

fn arrayAddSIMD(a: []const f32, b: []const f32, result: []f32) void {
    const Vec4 = @Vector(4, f32);
    var i: usize = 0;
    
    // 4要素ずつ処理
    while (i + 4 <= a.len) : (i += 4) {
        const va: Vec4 = a[i..][0..4].*;
        const vb: Vec4 = b[i..][0..4].*;
        const vr = va + vb;
        result[i..][0..4].* = vr;
    }
    
    // 残りをスカラー処理
    while (i < a.len) : (i += 1) {
        result[i] = a[i] + b[i];
    }
}

よくある間違い

サイズの不一致

// 間違い
const v1: @Vector(4, f32) = ...;
const v2: @Vector(3, f32) = ...;
const result = v1 + v2;  // エラー!

// 正しい
// 同じサイズのベクトルを使用

境界チェック

// 間違い
while (i < a.len) {
    const vec: Vec4 = a[i..][0..4].*;  // 境界を越える可能性
}

// 正しい
while (i + 4 <= a.len) {
    const vec: Vec4 = a[i..][0..4].*;
}

発展課題

  • FFT(高速フーリエ変換)
  • レイトレーシング
  • 行列乗算の最適化
  • コンボリューション
  • 画像フィルター

まとめ

ZigのSIMDは、型安全でありながら高いパフォーマンスを実現できます。適切に使用することで、数倍の高速化が可能です。