解答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は、型安全でありながら高いパフォーマンスを実現できます。適切に使用することで、数倍の高速化が可能です。