6

次のように、.NET で利用可能な SIMD 組み込み関数を使用して、長さ <= 8 の符号なし整数文字列を解析するメソッドを実装しました。

public unsafe static uint ParseUint(string text)
{
  fixed (char* c = text)
  {
    var parsed = Sse3.LoadDquVector128((byte*) c);
    var shift = (8 - text.Length) * 2;
    var shifted = Sse2.ShiftLeftLogical128BitLane(parsed, 
      (byte) (shift));

    Vector128<byte> digit0 = Vector128.Create((byte) '0');
    var reduced = Sse2.SubtractSaturate(shifted, digit0);

    var shortMult = Vector128.Create(10, 1, 10, 1, 10, 1, 10, 1);
    var collapsed2 = Sse2.MultiplyAddAdjacent(reduced.As<byte, short>(), shortMult);

    var repack = Sse41.PackUnsignedSaturate(collapsed2, collapsed2);
    var intMult = Vector128.Create((short)0, 0, 0, 0, 100, 1, 100, 1);
    var collapsed3 = Sse2.MultiplyAddAdjacent(repack.As<ushort,short>(), intMult);

    var e1 = collapsed3.GetElement(2);
    var e2 = collapsed3.GetElement(3);
    return (uint) (e1 * 10000 + e2);
  }
}

悲しいことに、ベースラインと比較するとuint.Parse()、次のようなやや印象に残らない結果が得られます。

方法 平均 エラー 標準偏差
ベースライン 15.157ns 0.0325ns 0.0304ns
ParseSimd 3.269ns 0.0115ns 0.0102ns

上記のコードを改善するには、どのような方法がありますか? 私が特に関心を持っている分野は次のとおりです。

  • SIMD レジスタのビット シフトが次のような計算で発生する方法text.Length
  • ~~ s のMultiplyAddAdjacentベクトルを含むを使用した UTF-16 データのアンパックと~~01
  • を使用して要素を抽出する方法GetElement()- おそらくToScalar()どこかで発生する可能性のある呼び出しがありますか?
4

3 に答える 3