🏹

Dart で SIMD を使う

2024/11/16に公開

概要

dart:typed_dataFloat32List などのデータを扱うとき, CoreML などのネイティブの機能を使った実装までするのは面倒だけど, もうちょっとパフォーマンス改善したい. そんな場面で SIMD を使うと Dart で書ける範囲でパフォーマンス改善できます.

関連するクラス

float32, float64, int32 に対応するクラスがあります.

ここでは, サイズが同じ二つの Float32List の各成分に同じ二項演算(和など)を施す例を示します.
可能な限り Float32x4 で処理して, 最後の余りを double で処理しています.

Float32List simdBinaryOperation(
  Float32List list1,
  Float32List list2, {
  required Float32x4 Function(Float32x4, Float32x4) simdOperation,
  required double Function(double, double) remainingOperation,
}) {
  if (list1.length != list2.length) {
    throw ArgumentError(
      'Lists must have the same length: '
      '${list1.length} != ${list2.length}',
    );
  }

  final resultData = Float32List(list1.length);
  final simdIterations = list1.length ~/ 4;

  for (var simdIndex = 0; simdIndex < simdIterations; simdIndex++) {
    final index = simdIndex * 4;
    final simdValue = simdOperation(
      Float32x4(
        list1[index],
        list1[index + 1],
        list1[index + 2],
        list1[index + 3],
      ),
      Float32x4(
        list2[index],
        list2[index + 1],
        list2[index + 2],
        list2[index + 3],
      ),
    );
    resultData[index] = simdValue.x;
    resultData[index + 1] = simdValue.y;
    resultData[index + 2] = simdValue.z;
    resultData[index + 3] = simdValue.w;
  }

  for (var index = simdIterations * 4; index < list1.length; index++) {
    resultData[index] = remainingOperation(list1[index], list2[index]);
  }

  return resultData;
}

例えば, 各成分の間の和をとる場合, 次のように実装できます.
simdOperationa + bFloat32x4 に定義されている operator です.

Float32List simdAdd(
  Float32List list1,
  Float32List list2,
) =>
    simdBinaryOperation(
      list1,
      list2,
      simdOperation: (a, b) => a + b,
      remainingOperation: (a, b) => a + b,
    );

DartPad に実行できるコードを置いておきます. 和以外にも色々試してみてください.

https://dartpad.dev/?id=45cb36bfee1809ae47e58518f0a60d44

結論

この例のベンチマークなどはとっていませんが, パフォーマンスは向上しているはずです.
このように割と簡単な実装で画像処理などのパフォーマンス向上ができるので, パフォーマンスを改善したい場合の最初の選択肢として有力なのではないでしょうか.

Discussion