发布 VectorTraits v1.0,它是 C# 下增强SIMD向量运算的类库

发布 VectorTraits v1.0, 它是C#下增强SIMD向量运算的类库

VectorTraits: SIMD Vector type traits methods (SIMD向量类型的特征方法).

NuGet: https://www.nuget.org/packages/VectorTraits/1.0.0

源代码: https://github.com/zyl910/VectorTraits

用途

总所周知,使用SIMD指令集,能够加速 多媒体处理(图形、图像、音频、视频…)、人工智能、科学计算 等。
然而,传统的SIMD编程存在以下痛点:

  • 难以跨平台。因为不同的CPU体系,提供了不同的SIMD指令集,例如 X86与Arm平台的SIMD指令集存在很多差异。如果程序欲移植到另一平台下,则需要查找该平台的SIMD指令集手册,重新开发一遍。
  • 位宽难以升级。即使是同一个平台,随着发展,会逐渐增加位数更宽的指令集。例如X86平台,除了已淘汰的64位MMX系列指令外,提供了了 128位SSE指令集、256位的AVX指令集,且部分高端处理器开始支持 512位的AVX-512指令集。以前用128位SSE系列指令编写的算法,若想移植到256位的AVX指令集,需要重新开发一遍,才能充分利用更宽的SIMD指令集。
  • 代码可读性差,开发门槛高。很多现代C语言编译器为SIMD指令,映射了内在函数(Intrinsic Functions),比编写汇编代码要容易了不少,且可读性提升了不少。但是由于函数名使用了一些晦涩的缩写,且C语言不支持函数名重载,以及C语言本身的复杂性,导致代码可读性与开发难度,仍有较高的门槛。

2016年的 .NET Core 1.0 新增了 Vector<T> 等向量类型,在很大程度上解决了以上痛点。

  • 容易跨平台。.NET平台的程序,是通过JIT(Just-In-Time Compiler,即时编译器)运行的。只编写一套基于向量方法的算法,且仅需编译为一套程序。随后该程序在不同平台上运行时,向量方法会被JIT编译为平台特有的SIMD指令集,从而充分的享用硬件加速。
  • 位宽能自动升级。对于Vector<T>类型,它的长度不是固定的,而是与该处理器的最长向量寄存器相同。具体来说,若CPU支持AVX指令集(严格来说是AVX2及以上),Vector<T>类型便是256位;若CPU仅支持SSE指令集(严格来说是SSE2及以上),Vector<T>类型便是128位。简单来说,在编写程序时仅使用Vector<T>类型就行,程序运行时,JIT会自动使用最宽的SIMD指令集。
  • 代码可读性较高,降低了开发门槛。.NET平台下,向量类型的方法名都是用完整英文单词所组成,并充分利用了函数名重载等 C# 语法特点,使这些方法名既简洁、又清晰。使得代码可读性有了很大的提高。

向量类型Vector<T> 虽然设计的好,但它缺少许多重要的向量函数,如 Ceiling、Sum、Shift、Shuffle 等。导致很多算法,难以用向量类型来实现。
.NET 平台版本升级时, 有时会增加若干个向量方法。例如2022年发布的 .NET 7.0,增加了ShiftRightArithmetic、Shuffle 等函数。但目前的向量方法还是较少, 例如缺少饱和处理等.
为了解决缺少向量方法的问题,.NET Core 3.0开始支持了内在函数。这能让开发者直接使用SIMD指令集,但这又面临了难以跨平台与位宽难以升级等问题。随着 .NET 平台的不断升级,会增加了更多的内在函数。例如 .NET 5.0 增加了 Arm平台的内在函数。
对于开发类库, 不能仅支持 .NET 7.0,而是需要支持多个 .NET 版本。于是你会面临繁琐的版本检查与条件处理. 而且 .NET Standard 类库的最高版本(2.1),仍是是不支持Ceiling等向量方法的,导致版本检查更加繁琐.

本库致力于解决以上麻烦, 使您能更方便的编写跨平台的SIMD算法。
特点:

  • 支持低版本的 .NET 程序(.NET Standard 1.1, .NET Core 1.0, .NET Framework 4.5, …)。能使低版本的 .NET 程序,也能使用最新的向量函数. 例如 .NET 7.0所新增的 ShiftRightArithmetic、Shuffle 等。
  • 功能强. 除了参考高版本 .NET 的向量方法外,本库还参考内在函数,提供了很多有用的向量方法。例如 YClamp, YNarrowSaturate …
  • 性能高。本库能充分利用 X86、Arm架构的内在函数对向量类型的运算进行硬件加速,且能够享受内联编译优化。且本库解决了BCL的部分向量方法(如Multiply, Shuffle等)在一些平台上没有硬件加速的问题, 因它补充了硬件加速算法.
  • 软件算法也很快。若发现向量类型的某个方法不支持硬件加速时,.NET Bcl会切换为软件算法,但它软件算法很多是含有分支语句的,性能较差。而本库的软件算法,是高度优化的无分支算法。
  • 使用方便。本库不仅支持 Vector<T>,还支持 Vector128<T>/Vector256<T> 等向量类型。工具类的类名很好记(Vectors/Vector64s/Vector128s/Vector256s),且通过同名的泛型类提供了许多常用的向量常数。
  • 为每一个特征方法, 增加了一些获取信息的的属性. e.g. _AcceleratedTypes, _FullAcceleratedTypes .

提示: 在 Visual Studio 的 Disassembly窗口可以查看运行时的汇编代码. 例如在支持 Avx指令集的机器上运行时, Vectors.ShiftLeft_Const 会被内联编译优化为使用 vpsllw 指令. 且对于常量值(1), 会被编译为指令的立即数.

Vectors.ShiftLeft_use_inline.png

例2: 使用 Vectors.ShiftLeft_ArgsVectors.ShiftLeft_Core, 能将部分运算挪到循环外去提前处理. 例如在支持 Avx指令集的机器上运行时, 会在循环外设置好 xmm1, 随后在内循环的vpsllw指令里使用了它. 且这里展示了: 内联编译优化消除了冗余的 xmm/ymm 转换.

Vectors.ShiftLeft_Core_use_inline.png

简介

本库为向量类型提供了许多重要的算术方法(如 Shift, Shuffle, NarrowSaturate)及常数, 使您能更方便的编写跨平台的SIMD运算代码。它充分利用了 X86、Arm架构的内在函数实现硬件加速,且能够享受内联编译优化。

常用类型:

  • Vectors: 为向量类型, 提供了常用工具函数, e.g. Create(T/T[]/Span/ReadOnlySpan), CreatePadding, CreateRotate, CreateByFunc, CreateByDouble … 它还为向量提供了特征方法, e.g. ShiftLeft、ShiftRightArithmetic、ShiftRightLogical、Shuffle …
  • Vectors<T>: 为向量类型, 提供了各种元素类型的常数. e.g. Serial, SerialDesc, XyzwWMask, MantissaMask, MaxValue, MinValue, NormOne, FixedOne, E, Pi, Tau, VMaxByte, VReciprocalMaxSByte …
  • Vector64s/Vector128s/Vector256s: 为固定位宽的向量(Vector64/Vector128/Vector256),提供了常用工具函数与特征方法.
  • Vector64s<T>/Vector128s<T>/Vector256s<T>: 为固定位宽的向量,提供了各种元素类型的常数.
  • Scalars: 为标量类型, 提供了各种工具函数. e.g. GetByDouble, GetFixedByDouble, GetByBits, GetBitsMask …
  • Scalars<T>: 为标量类型, 提供了许多常数. e.g. ExponentBits, MantissaBits, MantissaMask, MaxValue, MinValue, NormOne, FixedOne, E, Pi, Tau, VMaxByte, VReciprocalMaxSByte …
  • VectorTextUtil: 提供了一些向量的文本性工具函数. e.g. GetHex, Format, WriteLine …

特征方法:

  • 支持 .NET Standard 2.1 新增的向量方法: ConvertToDouble, ConvertToInt32, ConvertToInt64, ConvertToSingle, ConvertToUInt32, ConvertToUInt64, Narrow, Widen .
  • 支持 .NET 5.0 新增的向量方法: Ceiling, Floor .
  • 支持 .NET 6.0 新增的向量方法: Sum .
  • 支持 .NET 7.0 新增的向量方法: ExtractMostSignificantBits, Shuffle, ShiftLeft, ShiftRightArithmetic, ShiftRightLogical .
  • 提供缩窄饱和的向量方法: YNarrowSaturate, YNarrowSaturateUnsigned .
  • 提供舍入的向量方法: YRoundToEven, YRoundToZero .
  • 提供换位的向量方法: YShuffleInsert, YShuffleKernel, YShuffleG2, YShuffleG4, YShuffleG4X2 . 且提供了 ShuffleControlG2/ShuffleControlG4 enum.
  • 完整列表: TraitsMethodList

支持的指令集:

  • x86
    • 256位向量: Avx, Avx2 .
  • Arm
    • 128位向量: AdvSimd .

入门指南

1) 通过NuGet安装

可在’包管理器控制台’里输入以下命令, 或是使用’包管理器’GUI来安装本库.

NuGet: PM> Install-Package VectorTraits

2) 用法示例

静态类 Vectors 提供了许多方法, 例如 CreateRotate, ShiftLeft, Shuffle.
泛型结构体 Vectors<T> 为常用常数提供了字段.

范例代码在 samples/VectorTraits.Sample 文件夹. 源代码如下.

using System;
using System.IO;
using System.Numerics;
#if NETCOREAPP3_0_OR_GREATER
using System.Runtime.Intrinsics;
#endif
using Zyl.VectorTraits;

namespace Zyl.VectorTraits.Sample {
    class Program {
        private static readonly TextWriter writer = Console.Out;
        static void Main(string[] args) {
            writer.WriteLine("VectorTraits.Sample");
            writer.WriteLine();
            VectorTraitsGlobal.Init(); // Initialization (初始化).
            TraitsOutput.OutputEnvironment(writer); // Output environment info. It depends on `VectorTraits.InfoInc`. This row can be deleted when only VectorTraits are used (输出环境信息. 它依赖 `VectorTraits.InfoInc`. 当仅使用 VectorTraits 时, 可以删除本行).
            writer.WriteLine();

            // -- Start --
            Vector<short> src = Vectors.CreateRotate<short>(0, 1, 2, 3, 4, 5, 6, 7); // The `Vectors` class provides some methods. For example, 'CreateRotate' is rotate fill (`Vectors` 类提供了许多方法. 例如 `CreateRotate` 是旋转填充).
            VectorTextUtil.WriteLine(writer, "src:\t{0}", src); // It can not only format the string, but also display the hexadecimal of each element in the vector on the right Easy to view vector data (它不仅能格式化字符串, 且会在右侧显示向量中各元素的十六进制. 便于查看向量数据).

            // ShiftLeft. It is a new vector method in `.NET 7.0` (左移位. 它是 `.NET 7.0` 新增的向量方法)
            const int shiftAmount = 1;
            Vector<short> shifted = Vectors.ShiftLeft(src, shiftAmount); // shifted[i] = src[i] << shiftAmount.
            VectorTextUtil.WriteLine(writer, "ShiftLeft:\t{0}", shifted);
#if NET7_0_OR_GREATER
            // Compare BCL function (与BCL的函数做对比).
            Vector<short> shiftedBCL = Vector.ShiftLeft(src, shiftAmount);
            VectorTextUtil.WriteLine(writer, "Equals to BCL ShiftLeft:\t{0}", shifted.Equals(shiftedBCL));
#endif
            // ShiftLeft_Const
            VectorTextUtil.WriteLine(writer, "Equals to ShiftLeft_Const:\t{0}", shifted.Equals(Vectors.ShiftLeft_Const(src, shiftAmount))); // If the parameter shiftAmount is a constant, you can also use the Vectors' ShiftLeft_Const method. It is faster in many scenarios (若参数 shiftAmount 是常数, 还可以使用 Vectors 的 ShiftLeft_Const 方法. 它在不少场景下更快).
            writer.WriteLine();

            // Shuffle. It is a new vector method in `.NET 7.0` (换位. 它是 `.NET 7.0` 新增的向量方法)
            Vector<short> desc = Vectors<short>.SerialDesc; // The generic structure 'Vectors<T>' provides fields for commonly used constants. For example, 'SerialDesc' is a descending order value (泛型结构体 `Vectors<T>` 为常用常数提供了字段. 例如 `SerialDesc` 是降序的顺序值).
            VectorTextUtil.WriteLine(writer, "desc:\t{0}", desc);
            Vector<short> dst = Vectors.Shuffle(shifted, desc); // dst[i] = shifted[desc[i]].
            VectorTextUtil.WriteLine(writer, "Shuffle:\t{0}", dst);
#if NET7_0_OR_GREATER
            // Compare BCL function (与BCL的函数做对比). 
            Vector<short> dstBCL = default; // Since `.NET 7.0`, the Shuffle method has been provided in Vector128/Vector256, but the Shuffle method has not yet been provided in Vector (自 `.NET 7.0` 开始, Vector128/Vector256 里提供了 Shuffle 方法, 但 Vector 里尚未提供 Shuffle 方法).
            if (Vector<short>.Count == Vector128<short>.Count) {
                dstBCL = Vector128.Shuffle(shifted.AsVector128(), desc.AsVector128()).AsVector();
            } else if (Vector<short>.Count == Vector256<short>.Count) {
                dstBCL = Vector256.Shuffle(shifted.AsVector256(), desc.AsVector256()).AsVector();
            }
            VectorTextUtil.WriteLine(writer, "Equals to BCL Shuffle:\t{0}", dst.Equals(dstBCL));
#endif
            // Shuffle_Args and Shuffle_Core
            Vectors.Shuffle_Args(desc, out var args0, out var args1); // The suffix is the `Args' method used for parameter calculation, which involves processing such as parameter transformation in advance It is suitable for external loop (后缀是 `Args` 的方法, 用于参数计算, 即提前进行参数变换等处理. 它适合放在外循环).
            Vector<short> dst2 = Vectors.Shuffle_Core(shifted, args0, args1); // The suffix is the `Core` method used for core calculations, which calculates based on cached parameters It is suitable for internal loop to improve performance (后缀是 `Core` 方法, 用于核心计算, 既根据已缓存的参数进行计算. 它适合放在内循环, 便于改善性能).
            VectorTextUtil.WriteLine(writer, "Equals to Shuffle_Core:\t{0}", dst.Equals(dst2));
            writer.WriteLine();

            // Show AcceleratedTypes.
            VectorTextUtil.WriteLine(writer, "ShiftLeft_AcceleratedTypes:\t{0}", Vectors.ShiftLeft_AcceleratedTypes);
            VectorTextUtil.WriteLine(writer, "Shuffle_AcceleratedTypes:\t{0}", Vectors.Shuffle_AcceleratedTypes);
        }
    }
}

3) 示例的运行结果

.NET7.0 on X86

程序: VectorTraits.Sample

VectorTraits.Sample

IsRelease:      True
EnvironmentVariable(PROCESSOR_IDENTIFIER):      Intel64 Family 6 Model 142 Stepping 10, GenuineIntel
Environment.ProcessorCount:     8
Environment.Is64BitProcess:     True
Environment.OSVersion:  Microsoft Windows NT 10.0.19045.0
Environment.Version:    7.0.3
Stopwatch.Frequency:    10000000
RuntimeEnvironment.GetRuntimeDirectory: C:\Program Files\dotnet\shared\Microsoft.NETCore.App\7.0.3\
RuntimeInformation.FrameworkDescription:        .NET 7.0.3
RuntimeInformation.OSArchitecture:      X64
RuntimeInformation.OSDescription:       Microsoft Windows 10.0.19045
RuntimeInformation.RuntimeIdentifier:   win10-x64
IntPtr.Size:    8
BitConverter.IsLittleEndian:    True
Vector.IsHardwareAccelerated:   True
Vector<byte>.Count:     32      # 256bit
Vector<float>.Count:    8       # 256bit
VectorTraitsGlobal.InitCheckSum:        7960959 # 0x0079797F
Vector<T>.Assembly.CodeBase:    file:///C:/Program Files/dotnet/shared/Microsoft.NETCore.App/7.0.3/System.Private.CoreLib.dll
GetTargetFrameworkDisplayName(VectorTextUtil):  .NET 7.0
GetTargetFrameworkDisplayName(TraitsOutput):    .NET 7.0
Vectors.Instance:       VectorTraits256Avx2

src:    <0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7>        # (0000 0001 0002 0003 0004 0005 0006 0007 0000 0001 0002 0003 0004 0005 0006 0007)
ShiftLeft:      <0, 2, 4, 6, 8, 10, 12, 14, 0, 2, 4, 6, 8, 10, 12, 14>  # (0000 0002 0004 0006 0008 000A 000C 000E 0000 0002 0004 0006 0008 000A 000C 000E)
Equals to BCL ShiftLeft:        True
Equals to ShiftLeft_Const:      True

desc:   <15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0>  # (000F 000E 000D 000C 000B 000A 0009 0008 0007 0006 0005 0004 0003 0002 0001 0000)
Shuffle:        <14, 12, 10, 8, 6, 4, 2, 0, 14, 12, 10, 8, 6, 4, 2, 0>  # (000E 000C 000A 0008 0006 0004 0002 0000 000E 000C 000A 0008 0006 0004 0002 0000)
Equals to BCL Shuffle:  True
Equals to Shuffle_Core: True

ShiftLeft_AcceleratedTypes:     SByte, Byte, Int16, UInt16, Int32, UInt32, Int64, UInt64        # (00001FE0)
Shuffle_AcceleratedTypes:       SByte, Byte, Int16, UInt16, Int32, UInt32, Int64, UInt64, Single, Double        # (00007FE0)

注: Vectors.Instance 及之前的文本, 是TraitsOutput.OutputEnvironment输出的环境信息. 而从 src 开始的, 才是示例的主体代码.
由于CPU支持X86的Avx2指令集, 于是 Vector<byte>.Count 为 32(256bit), Vectors.InstanceVectorTraits256Avx2.

.NET7.0 on Arm

程序: VectorTraits.Sample

VectorTraits.Sample

IsRelease:	True
EnvironmentVariable(PROCESSOR_IDENTIFIER):	
Environment.ProcessorCount:	2
Environment.Is64BitProcess:	True
Environment.OSVersion:	Unix 5.19.0.1025
Environment.Version:	7.0.8
Stopwatch.Frequency:	1000000000
RuntimeEnvironment.GetRuntimeDirectory:	/home/ubuntu/.dotnet/shared/Microsoft.NETCore.App/7.0.8/
RuntimeInformation.FrameworkDescription:	.NET 7.0.8
RuntimeInformation.OSArchitecture:	Arm64
RuntimeInformation.OSDescription:	Linux 5.19.0-1025-aws #26~22.04.1-Ubuntu SMP Mon Apr 24 01:58:03 UTC 2023
RuntimeInformation.RuntimeIdentifier:	ubuntu.22.04-arm64
IntPtr.Size:	8
BitConverter.IsLittleEndian:	True
Vector.IsHardwareAccelerated:	True
Vector<byte>.Count:	16	# 128bit
Vector<float>.Count:	4	# 128bit
VectorTraitsGlobal.InitCheckSum:	7960961	# 0x00797981
Vector<T>.Assembly.CodeBase:	file:///home/ubuntu/.dotnet/shared/Microsoft.NETCore.App/7.0.8/System.Private.CoreLib.dll
GetTargetFrameworkDisplayName(VectorTextUtil):	.NET 7.0
GetTargetFrameworkDisplayName(TraitsOutput):	.NET 7.0
Vectors.Instance:	VectorTraits128AdvSimdB64

src:	<0, 1, 2, 3, 4, 5, 6, 7>	# (0000 0001 0002 0003 0004 0005 0006 0007)
ShiftLeft:	<0, 2, 4, 6, 8, 10, 12, 14>	# (0000 0002 0004 0006 0008 000A 000C 000E)
Equals to BCL ShiftLeft:	True
Equals to ShiftLeft_Const:	True

desc:	<7, 6, 5, 4, 3, 2, 1, 0>	# (0007 0006 0005 0004 0003 0002 0001 0000)
Shuffle:	<14, 12, 10, 8, 6, 4, 2, 0>	# (000E 000C 000A 0008 0006 0004 0002 0000)
Equals to BCL Shuffle:	True
Equals to Shuffle_Core:	True

ShiftLeft_AcceleratedTypes:	SByte, Byte, Int16, UInt16, Int32, UInt32, Int64, UInt64	# (00001FE0)
Shuffle_AcceleratedTypes:	SByte, Byte, Int16, UInt16, Int32, UInt32, Int64, UInt64, Single, Double	# (00007FE0)

运算结果与X86的相同,只是环境信息不同。
由于CPU支持Arm的AdvSimd指令集, 于是 Vector<byte>.Count 为 16(128bit), Vectors.InstanceVectorTraits128AdvSimdB64.

.NET Framework 4.5 on X86

程序: VectorTraits.Sample.NetFw.

VectorTraits.Sample

IsRelease:      True
EnvironmentVariable(PROCESSOR_IDENTIFIER):      Intel64 Family 6 Model 142 Stepping 10, GenuineIntel
Environment.ProcessorCount:     8
Environment.Is64BitProcess:     True
Environment.OSVersion:  Microsoft Windows NT 6.2.9200.0
Environment.Version:    4.0.30319.42000
Stopwatch.Frequency:    10000000
RuntimeEnvironment.GetRuntimeDirectory: C:\Windows\Microsoft.NET\Framework64\v4.0.30319\
RuntimeInformation.FrameworkDescription:        .NET Framework 4.8.9167.0
RuntimeInformation.OSArchitecture:      X64
RuntimeInformation.OSDescription:       Microsoft Windows 10.0.19045
IntPtr.Size:    8
BitConverter.IsLittleEndian:    True
Vector.IsHardwareAccelerated:   True
Vector<byte>.Count:     32      # 256bit
Vector<float>.Count:    8       # 256bit
VectorTraitsGlobal.InitCheckSum:        -25396097       # 0xFE7C7C7F
Vector<T>.Assembly.CodeBase:    file:///E:/zylSelf/Code/cs/base/VectorTraits/samples/VectorTraits.Sample.NetFw/bin/Release/System.Numerics.Vectors.DLL
GetTargetFrameworkDisplayName(VectorTextUtil):  .NET Standard 1.1
GetTargetFrameworkDisplayName(TraitsOutput):    .NET Framework 4.5
Vectors.Instance:       VectorTraits256Base

src:    <0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7>        # (0000 0001 0002 0003 0004 0005 0006 0007 0000 0001 0002 0003 0004 0005 0006 0007)
ShiftLeft:      <0, 2, 4, 6, 8, 10, 12, 14, 0, 2, 4, 6, 8, 10, 12, 14>  # (0000 0002 0004 0006 0008 000A 000C 000E 0000 0002 0004 0006 0008 000A 000C 000E)
Equals to ShiftLeft_Const:      True

desc:   <15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0>  # (000F 000E 000D 000C 000B 000A 0009 0008 0007 0006 0005 0004 0003 0002 0001 0000)
Shuffle:        <14, 12, 10, 8, 6, 4, 2, 0, 14, 12, 10, 8, 6, 4, 2, 0>  # (000E 000C 000A 0008 0006 0004 0002 0000 000E 000C 000A 0008 0006 0004 0002 0000)
Equals to Shuffle_Core: True

ShiftLeft_AcceleratedTypes:     SByte, Byte, Int16, UInt16, Int32, UInt32       # (000007E0)
Shuffle_AcceleratedTypes:       None    # (00000000)

Vectors 的 ShiftLeft/Shuffle 都能正常工作.
由于CPU支持X86的Avx2指令集, 于是 Vector<byte>.Count 为 32(256bit). Vectors.InstanceVectorTraits256Base. 它不是 VectorTraits256Avx2, 是因为直到 .NET Core 3.0 才支持内在函数.
ShiftLeft_AcceleratedTypes的值含有“Int16”等类型,这表示ShiftLeft在使用这些类型时, 是存在硬件加速的. 本库巧妙的利用了向量算法, 即使在没有内在函数时,也尽量实现了硬件加速.

基准测试结果

数据的单位: 百万次操作/秒. 数字越大, 性能越好.

ShiftLeft

ShiftLeft: 将向量的每个元素左移指定量.
它是.NET 7.0所新增的向量方法.

ShiftLeft - x86 - lntel Core i5-8250U
TypeMethod.NET Framework.NET Core 2.1.NET Core 3.1.NET 5.0.NET 6.0.NET 7.0
ByteSumSLLScalar853.802817.5281104.9931118.3811374.2551480.225
ByteSumSLLNetBcl1128.290
ByteSumSLLNetBcl_Const1137.564
ByteSumSLLTraits8296.6828114.08521811.57319960.73221044.19223074.627
ByteSumSLLTraits_Core33328.33335503.28541644.14635703.81636615.13832872.874
ByteSumSLLConstTraits10849.89910168.75425029.29029761.73733785.50232862.094
ByteSumSLLConstTraits_Core36537.66831837.58639307.52335698.90935679.74433994.997
Int16SumSLLScalar823.668806.3951176.1331183.9661379.4981486.900
Int16SumSLLNetBcl18445.571
Int16SumSLLNetBcl_Const19054.243
Int16SumSLLTraits5076.0365047.45316986.36116653.32916496.18216114.543
Int16SumSLLTraits_Core20318.98418959.03320182.65517683.71718500.30218439.182
Int16SumSLLConstTraits5899.2565693.08416944.67319378.43421059.68219572.551
Int16SumSLLConstTraits_Core20172.95219339.31118407.67319850.71121232.27918136.492
Int32SumSLLScalar803.506820.6391307.6141328.7032199.6851587.071
Int32SumSLLNetBcl9469.894
Int32SumSLLNetBcl_Const10657.900
Int32SumSLLTraits2571.4562678.8668246.4027799.7488221.3829594.126
Int32SumSLLTraits_Core8574.3618465.71210320.83310408.38110626.91010035.217
Int32SumSLLConstTraits1493.5902922.1038155.0469293.14810579.40010185.431
Int32SumSLLConstTraits_Core8467.9748554.9209784.69910384.7329790.89810329.112
Int64SumSLLScalar797.703816.5041295.0091305.6112043.5271535.809
Int64SumSLLNetBcl4143.077
Int64SumSLLNetBcl_Const4903.130
Int64SumSLLTraits426.950458.5173867.1363941.9993964.7623713.754
Int64SumSLLTraits_Core441.378463.5374802.9114813.0184776.1824653.104
Int64SumSLLConstTraits490.135536.9493929.1094018.0724725.2934712.366
Int64SumSLLConstTraits_Core491.263531.9464930.0994737.4624782.4304371.649

说明:

  • SumSLLScalar: 使用标量算法.
  • SumSLLNetBcl: 使用BCL的方法(Vector.ShiftLeft), 参数是变量. 注意 .NET 7.0 才提供该方法.
  • SumSLLNetBcl_Const: 使用BCL的方法(Vector.ShiftLeft), 参数是常量. 注意 .NET 7.0 才提供该方法.
  • SumSLLTraits: 使用本库的普通方法(Vectors.ShiftLeft), 参数是变量.
  • SumSLLTraits_Core: 使用本库的 Core 后缀的方法(Vectors.ShiftLeft_Args, Vectors.ShiftLeft_Core), 参数是变量.
  • SumSLLConstTraits: 使用本库的 Const 后缀的方法(Vectors.ShiftLeft_Const), 参数是常量.
  • SumSLLConstTraits_Core: 使用本库的 ConstCore 后缀的方法(Vectors.ShiftLeft_Args, Vectors.ShiftLeft_ConstCore), 参数是常量.

BCL的方法(Vector.ShiftLeft) 在X86平台运行时, 仅 Int16/Int32/Int64 有硬件加速, 而 Byte 没有硬件加速. 这是可能是因为 Avx2 指令集仅有 16~64位 的左移位指令, 未提供其他类型的指令, BCL便转为软件算法了.
而本库对于这些数字类型, 会换成由其他指令组合实现的高效算法. 例如对于 Byte类型, SumSLLConstTraits_Core 在.NET 7.0的值为“32872.874”, 性能是 标量算法的 32872.874/1480.225≈22.2080 倍, 且是BCL方法的 32872.874/1137.564≈28.8976 倍.
因为X86的内在函数是从.NET Core 3.0开始才提供的. 故对于 Int64类型, 在 .NET Core 3.0 之后才有硬件加速.

对于ShiftLeft来说, 当参数shiftAmount 是常量时, 性能一般会比用变量时更高. 无论是 BCL还是本库的方法, 都是如此.
使用本库的 Core 后缀的方法, 能将部分运算挪到循环外去提前处理, 从而优化了性能. 而当 CPU提供了常数参数的指令时(专业术语是“立即数参数”), 该指令的性能一般会更高. 于是本库还提供了 ConstCore 后缀的方法, 会选择该平台最快的指令.
因“CPU睿频”、“其他进程抢占CPU资源”等因素, 有时性能波动比较大. 但请放心, 已经检查过了Release的程序运行时的汇编指令, 它已经是按最佳硬件指令运行的. 例如下图.

Vectors.ShiftLeft_Core_use_inline.png

ShiftLeft - Arm - AWS Arm t4g.small
TypeMethod.NET Core 3.1.NET 5.0.NET 6.0.NET 7.0
ByteSumSLLScalar610.192610.563653.197891.088
ByteSumSLLNetBcl19580.464
ByteSumSLLNetBcl_Const19599.073
ByteSumSLLTraits5668.03613252.89113253.57513241.598
ByteSumSLLTraits_Core14341.89515888.31515887.52019595.005
ByteSumSLLConstTraits9946.66313243.30415895.67219466.408
ByteSumSLLConstTraits_Core13201.65715896.74815894.09319447.318
Int16SumSLLScalar606.942607.226607.742765.154
Int16SumSLLNetBcl9332.186
Int16SumSLLNetBcl_Const9240.256
Int16SumSLLTraits4231.3106553.0726603.4319351.061
Int16SumSLLTraits_Core7881.8347897.8788449.5029356.142
Int16SumSLLConstTraits6577.8296620.0788444.3049359.246
Int16SumSLLConstTraits_Core8383.1077923.1198443.8029317.663
Int32SumSLLScalar749.491746.414747.2731403.533
Int32SumSLLNetBcl4537.804
Int32SumSLLNetBcl_Const4533.257
Int32SumSLLTraits3233.2143531.4413530.3894545.497
Int32SumSLLTraits_Core3901.9754140.1714142.3774505.555
Int32SumSLLConstTraits3510.4713865.2854134.1084568.054
Int32SumSLLConstTraits_Core3905.8293895.8983896.7194547.294
Int64SumSLLScalar743.187742.685743.7601372.299
Int64SumSLLNetBcl2473.172
Int64SumSLLNetBcl_Const2468.456
Int64SumSLLTraits482.0561637.2321640.5471981.831
Int64SumSLLTraits_Core488.0721970.1522088.7932468.202
Int64SumSLLConstTraits467.9421958.4322099.0952460.619
Int64SumSLLConstTraits_Core470.1121971.8982097.6932465.419

说明:

  • SumSLLScalar: 使用标量算法.
  • SumSLLNetBcl: 使用BCL的方法(Vector.ShiftLeft), 参数是变量. 注意 .NET 7.0 才提供该方法.
  • SumSLLNetBcl_Const: 使用BCL的方法(Vector.ShiftLeft), 参数是常量. 注意 .NET 7.0 才提供该方法.
  • SumSLLTraits: 使用本库的普通方法(Vectors.ShiftLeft), 参数是变量.
  • SumSLLTraits_Core: 使用本库的 Core 后缀的方法(Vectors.ShiftLeft_Args, Vectors.ShiftLeft_Core), 参数是变量.
  • SumSLLConstTraits: 使用本库的 Const 后缀的方法(Vectors.ShiftLeft_Const), 参数是常量.
  • SumSLLConstTraits_Core: 使用本库的 ConstCore 后缀的方法(Vectors.ShiftLeft_Args, Vectors.ShiftLeft_ConstCore), 参数是常量.

BCL的方法(Vector.ShiftLeft) 在Arm平台运行时, 整数类型都有硬件加速. 对于8~64位整数的左移位, AdvSimd指令集都提供了专用指令.
本库在Arm平台运行时, 也使用了同样的指令. 于是性能接近.
因为从 .NET 5.0开始, 才提供了 Arm的内在函数. 故对于 Int64类型, 在 .NET 5.0 之后才有硬件加速.

ShiftRightArithmetic

ShiftRightArithmetic: 将向量的每个有符号元素算术右移指定量.
它是.NET 7.0所新增的向量方法.

ShiftRightArithmetic - x86 - lntel Core i5-8250U
TypeMethod.NET Framework.NET Core 2.1.NET Core 3.1.NET 5.0.NET 6.0.NET 7.0
Int16SumSRAScalar823.804827.7341180.9331182.3071341.1711592.939
Int16SumSRANetBcl18480.038
Int16SumSRANetBcl_Const21052.686
Int16SumSRATraits1557.1321559.67417325.18417699.94416372.79917193.661
Int16SumSRATraits_Core1653.8161653.71418414.63219664.14717938.06818476.248
Int16SumSRAConstTraits1672.2581675.04417658.70320409.88920233.73820835.294
Int16SumSRAConstTraits_Core1714.5821667.09020076.04320212.77420994.71721053.837
Int32SumSRAScalar825.056829.7891275.7991342.3491621.2951620.315
Int32SumSRANetBcl10132.774
Int32SumSRANetBcl_Const11033.258
Int32SumSRATraits764.013759.5888195.4708298.4048314.9219937.082
Int32SumSRATraits_Core826.612825.85410576.36710449.5359783.71611108.074
Int32SumSRAConstTraits837.650834.1268484.9599238.0899979.23610053.944
Int32SumSRAConstTraits_Core856.397859.42610201.12510314.33411009.38410772.948
Int64SumSRAScalar815.238811.6451300.0521280.9821322.4411602.916
Int64SumSRANetBcl578.499
Int64SumSRANetBcl_Const553.963
Int64SumSRATraits447.196441.6903032.9032830.9352988.1302922.851
Int64SumSRATraits_Core459.781458.2693639.0923352.2553336.9743488.018
Int64SumSRAConstTraits491.449491.4203074.9262820.8643365.6423397.660
Int64SumSRAConstTraits_Core496.174491.0223660.3803365.2103398.6573237.150
SByteSumSRAScalar827.231823.6431101.5181105.2441348.3401619.984
SByteSumSRANetBcl1161.428
SByteSumSRANetBcl_Const1156.552
SByteSumSRATraits3108.5693100.70317944.55517103.39917926.97520115.939
SByteSumSRATraits_Core3298.4913288.74230742.09530212.46929604.49833040.654
SByteSumSRAConstTraits3320.8133327.91018297.66925989.44628437.42531118.235
SByteSumSRAConstTraits_Core3423.8683427.68129454.03227559.31630075.33830565.076

说明:

  • SumSRAScalar: 使用标量算法.
  • SumSRANetBcl: 使用BCL的方法(Vector.ShiftRightArithmetic), 参数是变量. 注意 .NET 7.0 才提供该方法.
  • SumSRANetBcl_Const: 使用BCL的方法(Vector.ShiftRightArithmetic), 参数是常量. 注意 .NET 7.0 才提供该方法.
  • SumSRATraits: 使用本库的普通方法(Vectors.ShiftRightArithmetic), 参数是变量.
  • SumSRATraits_Core: 使用本库的 Core 后缀的方法(Vectors.ShiftRightArithmetic_Args, Vectors.ShiftRightArithmetic_Core), 参数是变量.
  • SumSRAConstTraits: 使用本库的 Const 后缀的方法(Vectors.ShiftRightArithmetic_Const), 参数是常量.
  • SumSRAConstTraits_Core: 使用本库的 ConstCore 后缀的方法(Vectors.ShiftRightArithmetic_Args, Vectors.ShiftRightArithmetic_ConstCore), 参数是常量.

BCL的方法(Vector.ShiftRightArithmetic) 在X86平台运行时, 仅 Int16/Int32 有硬件加速, 而 SByte/Int64 没有硬件加速. 这是可能是因为 Avx2 指令集仅有 16~32位 的算术右移位指令.
而本库对于这些数字类型, 会换成由其他指令组合实现的高效算法. 从 .NET Core 3.0 开始, 具有硬件加速.

ShiftRightArithmetic - Arm - AWS Arm t4g.small
TypeMethod.NET Core 3.1.NET 5.0.NET 6.0.NET 7.0
Int16SumSRAScalar587.279541.166607.230822.580
Int16SumSRANetBcl9941.333
Int16SumSRANetBcl_Const9938.477
Int16SumSRATraits1559.1384950.4805645.4979938.217
Int16SumSRATraits_Core1823.5098388.9567904.3669938.584
Int16SumSRAConstTraits1808.9656589.8817892.4079871.343
Int16SumSRAConstTraits_Core1810.5278392.9437896.2209925.543
Int32SumSRAScalar712.668746.666747.0551188.551
Int32SumSRANetBcl4861.897
Int32SumSRANetBcl_Const4859.816
Int32SumSRATraits779.7872944.1692945.0264868.865
Int32SumSRATraits_Core914.3464125.7484135.3534862.075
Int32SumSRAConstTraits884.9143266.2723892.0164841.364
Int32SumSRAConstTraits_Core920.3894134.1643893.0884844.364
Int64SumSRAScalar717.640742.361742.3371189.925
Int64SumSRANetBcl2468.196
Int64SumSRANetBcl_Const2471.434
Int64SumSRATraits451.9561235.4291233.8181420.116
Int64SumSRATraits_Core435.1801972.7341966.9922465.932
Int64SumSRAConstTraits437.7991962.0841966.9462470.825
Int64SumSRAConstTraits_Core436.4192099.3032097.2962469.149
SByteSumSRAScalar577.766610.669672.786925.515
SByteSumSRANetBcl19792.701
SByteSumSRANetBcl_Const19792.641
SByteSumSRATraits2991.22811281.22911275.75811356.994
SByteSumSRATraits_Core3529.32616818.29716827.84419798.924
SByteSumSRAConstTraits3476.13815680.87316829.92019774.470
SByteSumSRAConstTraits_Core3577.92716813.20215762.24319759.552

说明:

  • SumSRAScalar: 使用标量算法.
  • SumSRANetBcl: 使用BCL的方法(Vector.ShiftRightArithmetic), 参数是变量. 注意 .NET 7.0 才提供该方法.
  • SumSRANetBcl_Const: 使用BCL的方法(Vector.ShiftRightArithmetic), 参数是常量. 注意 .NET 7.0 才提供该方法.
  • SumSRATraits: 使用本库的普通方法(Vectors.ShiftRightArithmetic), 参数是变量.
  • SumSRATraits_Core: 使用本库的 Core 后缀的方法(Vectors.ShiftRightArithmetic_Args, Vectors.ShiftRightArithmetic_Core), 参数是变量.
  • SumSRAConstTraits: 使用本库的 Const 后缀的方法(Vectors.ShiftRightArithmetic_Const), 参数是常量.
  • SumSRAConstTraits_Core: 使用本库的 ConstCore 后缀的方法(Vectors.ShiftRightArithmetic_Args, Vectors.ShiftRightArithmetic_ConstCore), 参数是常量.

BCL的方法(Vector.ShiftRightArithmetic) 在Arm平台运行时, 整数类型都有硬件加速. 对于8~64位整数的算术右移位, AdvSimd指令集都提供了专用指令.
本库在Arm平台运行时, 也使用了同样的指令. 于是性能接近. 从 .NET 5.0 开始, 具有硬件加速.

Shuffle

Shuffle: 换位并清零. 通过使用一组索引从输入向量中选择值,来创建一个新向量.
它是.NET 7.0所新增的向量方法. 自 .NET 7.0 开始, Vector128/Vector256 里提供了 Shuffle 方法, 但 Vector 里尚未提供 Shuffle 方法.

Shuffle 允许索引超过有效范围, 此次会将对应元素置0. 这个特性会稍微拖慢性能, 于是本库还提供了 YShuffleKernel 方法(仅换位). 若能确保索引总是在有效范围内, 用 YShuffleKernel 更快.

Shuffle - x86 - lntel Core i5-8250U
TypeMethod.NET Framework.NET Core 2.1.NET Core 3.1.NET 5.0.NET 6.0.NET 7.0
Int16SumScalar1009.1321007.748992.2991004.3701034.912989.043
Int16Sum256_Bcl775.841
Int16SumTraits1012.6261008.9006025.6298058.0758017.2789060.106
Int16SumTraits_Args01008.925988.64614845.37014590.24614413.19314209.436
Int16SumTraits_Args1008.981991.79014644.21914527.03514198.71814024.591
Int16SumKernelTraits1011.5281009.2897566.2669381.2279585.57310330.592
Int16SumKernelTraits_Args01006.331989.48815045.75314575.46014464.14714484.413
Int16SumKernelTraits_Args1017.264990.16114900.55313672.16714556.62714280.139
Int32SumScalar723.019725.013704.809708.372735.378747.651
Int32Sum256_Bcl611.393
Int32SumTraits716.509724.3695216.7575813.2067139.3379250.625
Int32SumTraits_Args0716.520703.6369278.5079221.3109159.6839728.639
Int32SumTraits_Args722.854709.6549010.8349164.8548992.3569828.623
Int32SumKernelTraits722.441725.2189554.7667064.7116932.1929996.960
Int32SumKernelTraits_Args0724.689706.34511017.87411092.30111134.92411279.116
Int32SumKernelTraits_Args727.981701.15511030.88610970.11610510.20811324.558
Int64SumScalar459.881457.952188.562477.806459.242462.021
Int64Sum256_Bcl515.863
Int64SumTraits459.302459.8762143.1292518.3252433.4493524.309
Int64SumTraits_Args0465.064441.5764508.7544449.0984406.9944484.512
Int64SumTraits_Args459.786408.5454466.0284214.8084293.4384270.565
Int64SumKernelTraits460.058458.8582702.1053195.8101714.7354046.124
Int64SumKernelTraits_Args0464.705438.2244820.7674705.8434042.2624882.344
Int64SumKernelTraits_Args463.218411.9054884.2775433.5584140.5294788.233
SByteSumScalar1263.2101262.732844.7491013.9241077.5131261.932
SByteSum256_Bcl930.329
SByteSumTraits1264.3931264.66713239.40817766.24216140.96424537.440
SByteSumTraits_Args01262.3681242.50331793.48731423.34431314.48834322.789
SByteSumTraits_Args1221.5421248.12131118.40031615.12031980.79433156.240
SByteSumKernelTraits1260.0971266.05619996.80623032.25023853.31429612.169
SByteSumKernelTraits_Args01260.4611245.53031084.95530974.02231913.28733643.052
SByteSumKernelTraits_Args1260.2721249.31630827.15230734.83132311.41832977.071

说明:

  • SumScalar: 使用标量算法.
  • Sum256_Bcl: 使用BCL的方法(Vector256.Shuffle).
  • SumTraits: 使用本库的普通方法(Vectors.Shuffle).
  • SumTraits_Args0: 使用本库的 Core 后缀的方法(Vectors.Shuffle_Args, Vectors.Shuffle_Core), 不使用ValueTuple, 而是用“out”关键字返回多个值.
  • SumTraits_Args: 使用本库的 Core 后缀的方法(Vectors.Shuffle_Args, Vectors.Shuffle_Core), 使用ValueTuple.
  • SumKernelTraits: 使用本库的YShuffleKernel的普通方法(Vectors.YShuffleKernel).
  • SumKernelTraits_Args0: 使用本库的YShuffleKernel的 Core 后缀的方法(Vectors.YShuffleKernel_Args, Vectors.YShuffleKernel_Core), 不使用ValueTuple, 而是用“out”关键字返回多个值.
  • SumKernelTraits_Args: 使用本库的YShuffleKernel的 Core 后缀的方法(Vectors.YShuffleKernel_Args, Vectors.YShuffleKernel_Core), 使用ValueTuple.

BCL的方法(Vector.Shuffle) 在X86平台运行时, 所有数字类型, 均没有硬件加速.
而本库对于这些数字类型, 会换成由其他指令组合实现的高效算法. 从 .NET Core 3.0 开始, 具有硬件加速.
使用本库的 Core 后缀的方法, 能将部分运算挪到循环外去提前处理, 从而优化了性能. 特别对于Shuffle方法来说, 性能提升幅度较大.
若能确保索引总是在有效范围内, 能用 YShuffleKernel 替代Shuffle. 它更快.
对于Args 后缀的方法, 除了可以用“out”关键字返回多个值外, 还可以用 ValueTuple 来接收多个值, 简化了代码. 但得注意 ValueTuple 有时会降低性能.

Shuffle - Arm - AWS Arm t4g.small
TypeMethod.NET Core 3.1.NET 5.0.NET 6.0.NET 7.0
Int16SumScalar424.835422.286423.070526.071
Int16Sum128_Bcl482.320
Int16SumTraits423.9424925.0344938.0775853.245
Int16SumTraits_Args0423.8728381.3957862.0559821.786
Int16SumTraits_Args400.7672982.7552976.1389769.321
Int16Sum128_AdvSimd3169.0363115.8593239.207
Int16SumKernelTraits424.3175644.8086565.5197904.834
Int16SumKernelTraits_Args0423.8997881.8237847.8689835.768
Int16SumKernelTraits_Args399.7722982.0132868.2869778.383
Int32SumScalar288.211281.081276.668317.268
Int32Sum128_Bcl303.702
Int32SumTraits287.9422447.8122561.5012912.918
Int32SumTraits_Args0286.6464103.0844110.5504796.704
Int32SumTraits_Args268.6131487.1801483.9944775.891
Int32SumKernelTraits287.9002805.3553237.3453909.519
Int32SumKernelTraits_Args0286.5564112.6894128.4024825.180
Int32SumKernelTraits_Args268.8581487.0211430.4004755.708
Int64SumScalar378.628188.199447.044552.523
Int64Sum128_Bcl712.025
Int64SumTraits379.6431015.8111089.6281242.552
Int64SumTraits_Args0380.1332091.9481967.7662465.800
Int64SumTraits_Args326.603743.033744.9082452.967
Int64SumKernelTraits379.6961221.9231480.1821756.478
Int64SumKernelTraits_Args0379.7882096.1242095.5362464.674
Int64SumKernelTraits_Args170.957715.532717.5492457.398
SByteSumScalar668.450650.673659.984833.921
SByteSum128_Bcl648.985
SByteSumTraits667.52713135.35616713.00919730.059
SByteSumTraits_Args0664.98815734.26415708.75819741.441
SByteSumTraits_Args625.4105723.5235948.76619692.665
SByteSumKernelTraits667.28015584.50515643.22519741.523
SByteSumKernelTraits_Args0664.91416731.94216685.53419726.599
SByteSumKernelTraits_Args625.7615723.9105950.54919685.073

说明:

  • SumScalar: 使用标量算法.
  • Sum128_Bcl: 使用BCL的方法(Vector128.Shuffle).
  • SumTraits: 使用本库的普通方法(Vectors.Shuffle).
  • SumTraits_Args0: 使用本库的 Core 后缀的方法(Vectors.Shuffle_Args, Vectors.Shuffle_Core), 不使用ValueTuple, 而是用“out”关键字返回多个值.
  • SumTraits_Args: 使用本库的 Core 后缀的方法(Vectors.Shuffle_Args, Vectors.Shuffle_Core), 使用ValueTuple.
  • SumKernelTraits: 使用本库的YShuffleKernel的普通方法(Vectors.YShuffleKernel).
  • SumKernelTraits_Args0: 使用本库的YShuffleKernel的 Core 后缀的方法(Vectors.YShuffleKernel_Args, Vectors.YShuffleKernel_Core), 不使用ValueTuple, 而是用“out”关键字返回多个值.
  • SumKernelTraits_Args: 使用本库的YShuffleKernel的 Core 后缀的方法(Vectors.YShuffleKernel_Args, Vectors.YShuffleKernel_Core), 使用ValueTuple.

BCL的方法(Vector.Shuffle) 在Arm平台运行时, 所有数字类型, 均没有硬件加速.
而本库对于这些数字类型, 会换成由其他指令组合实现的高效算法. 从 .NET 5.0 开始, 具有硬件加速.
注意在.NET 7.0之前, SumTraits_Args 有时与 SumTraits_Args0 的性能相差较大, 这是因为ValueTuple 在Arm下的性能损失较大.

YNarrowSaturate

YNarrowSaturate: 将两个 Vector 实例饱和缩窄为一个 Vector .

YNarrowSaturate - x86 - lntel Core i5-8250U
TypeMethod.NET Framework.NET Core 2.1.NET Core 3.1.NET 5.0.NET 6.0.NET 7.0
Int16SumNarrow_If209.442209.620210.928199.480211.138215.694
Int16SumNarrow_MinMax202.714215.451212.224214.893175.099219.752
Int16SumNarrowVectorBase13095.09813774.47213161.16513013.47213168.23915964.293
Int16SumNarrowVectorTraits13024.36413662.39628118.83425049.00428198.28227819.176
Int32SumNarrow_If210.834212.404213.735214.810208.985222.597
Int32SumNarrow_MinMax212.099211.786210.670205.029210.333208.573
Int32SumNarrowVectorBase6933.0366441.0626584.0007382.2546728.3197703.530
Int32SumNarrowVectorTraits6856.4566398.52512533.50514263.83512888.77113992.887
Int64SumNarrow_If195.128186.841195.864199.460193.475204.264
Int64SumNarrow_MinMax189.209178.971196.065191.231191.600203.201
Int64SumNarrowVectorBase1959.8061878.7242000.9762118.8581976.2642658.885
Int64SumNarrowVectorTraits1956.9081872.4652587.6362763.2822689.9312418.496
UInt16SumNarrow_If1066.840902.5161078.540974.7491067.7681083.124
UInt16SumNarrow_MinMax1066.895903.120901.484959.577900.228823.878
UInt16SumNarrowVectorBase16884.65817052.91415147.60217094.24317200.04319717.119
UInt16SumNarrowVectorTraits16862.58716975.92521142.03426121.17026440.90824575.123
UInt32SumNarrow_If1116.417961.764856.272901.272872.8111111.046
UInt32SumNarrow_MinMax1115.502902.014900.357877.358839.361854.364
UInt32SumNarrowVectorBase7824.6747015.9848617.5948176.9268059.9238801.283
UInt32SumNarrowVectorTraits7879.5567024.43812181.18010713.26011063.76511314.953
UInt64SumNarrow_If997.327847.431871.820875.547858.0601109.023
UInt64SumNarrow_MinMax865.4201083.4371107.6711095.561886.387735.609
UInt64SumNarrowVectorBase2015.3281971.9811833.6102446.3462636.1373336.732
UInt64SumNarrowVectorTraits2020.4051979.0782918.8283258.7963341.1843108.173

说明:

  • SumNarrow_If: 基于if语句的标量算法.
  • SumNarrow_MinMax: 基于Math类的 Min/Max 方法的标量算法.
  • SumNarrowVectorBase: 使用本库的基础方法(VectorTraitsBase.Statics.YNarrowSaturate). 它是通过组合使用BCL的向量方法来实现的, 能够利用硬件加速.
  • SumNarrowVectorTraits: 使用本库的特征方法(Vectors.YNarrowSaturate). 它是通过内在函数来实现的, 能获得更佳硬件加速.

对于 16~32位整数, 在 .NET Core 3.1 之后, SumNarrowVectorTraits的性能比SumNarrowVectorBase强很多. 这是因为 X86提供了专门的指令。
对于 64位整数(Int64/UInt64), 虽然X86没有提供对应指令. 但由于 SumNarrowVectorTraits 版代码使用了更佳的内在函数算法, 所以在很多时候它的性能仍是比SumNarrowVectorBase 更强。

YNarrowSaturate - Arm - AWS Arm t4g.small
TypeMethod.NET Core 3.1.NET 5.0.NET 6.0.NET 7.0
Int16SumNarrow_If154.717163.350157.517181.894
Int16SumNarrow_MinMax160.654161.130108.656184.712
Int16SumNarrowVectorBase6124.5165210.8806055.7217165.511
Int16SumNarrowVectorTraits6125.11313574.32913433.47115507.867
Int32SumNarrow_If163.905165.250160.416190.897
Int32SumNarrow_MinMax155.399155.059159.092195.986
Int32SumNarrowVectorBase2701.8103219.2902766.2673025.432
Int32SumNarrowVectorTraits2703.7096306.0226210.7198003.142
Int64SumNarrow_If161.985162.089160.805205.371
Int64SumNarrow_MinMax154.244153.980165.349197.005
Int64SumNarrowVectorBase716.8801189.1921156.6271229.301
Int64SumNarrowVectorTraits716.6613282.4553283.9693921.550
UInt16SumNarrow_If525.100530.550525.952608.947
UInt16SumNarrow_MinMax528.430527.506539.088609.259
UInt16SumNarrowVectorBase7945.7778739.6157945.9138916.311
UInt16SumNarrowVectorTraits7943.11514158.58614166.20713814.007
UInt32SumNarrow_If544.871540.266538.649621.107
UInt32SumNarrow_MinMax541.719536.718535.769621.414
UInt32SumNarrowVectorBase4001.5904022.5043954.7234379.473
UInt32SumNarrowVectorTraits4018.8156824.6376400.9476722.416
UInt64SumNarrow_If620.408620.900622.076828.917
UInt64SumNarrow_MinMax620.012619.806622.201828.565
UInt64SumNarrowVectorBase1291.0511863.5431869.9041816.732
UInt64SumNarrowVectorTraits1293.9973233.7263491.3693501.256

说明:

  • SumNarrow_If: 基于if语句的标量算法.
  • SumNarrow_MinMax: 基于Math类的 Min/Max 方法的标量算法.
  • SumNarrowVectorBase: 使用本库的基础方法(VectorTraitsBase.Statics.YNarrowSaturate). 它是通过组合使用BCL的向量方法来实现的, 能够利用硬件加速.
  • SumNarrowVectorTraits: 使用本库的特征方法(Vectors.YNarrowSaturate). 它是通过内在函数来实现的, 能获得更佳硬件加速.

因为从 .NET 5.0开始,提供了 Arm的内在函数. 故从 .NET 5.0 开始, SumNarrowVectorTraits的性能比SumNarrowVectorBase强很多.

更多结果

详见: BenchmarkResults

文档

  • 特征方法列表: TraitsMethodList
  • DocFX: 运行 docfx_serve.bat. 随后浏览 http://localhost:8080/ .
  • Doxygen: 运行 Doxywizard, 点击菜单栏的 File->Open. 选择 Doxyfile 文件,并点击“OK”. 点击“Run”Tab, 点击“Run doxygen”按钮. 它会在“doc_gen”文件夹生成文档.

变更日志

[2023-09-07] v1.0

  • Major: 支持 x86的Avx指令集, 以及Arm的 AdvSimd 指令集; 支持 NET 5.0-7.0 新增的向量方法; 还提供了 4元素换位(YShuffleG4)、饱和变窄(YNarrowSaturate, YNarrowSaturateUnsigned) 等原创的向量方法.
  • 为向量类型提供了一些工具方法及常数. e.g. Vectors, Vector64s, Vector128s, Vector256s, VectorTextUtil …
  • 支持 .NET Standard 2.1 新增的向量方法: ConvertToDouble, ConvertToInt32, ConvertToInt64, ConvertToSingle, ConvertToUInt32, ConvertToUInt64, Narrow, Widen .
  • 支持 .NET 5.0 新增的向量方法: Ceiling, Floor .
  • 支持 .NET 6.0 新增的向量方法: Sum .
  • 支持 .NET 7.0 新增的向量方法: ExtractMostSignificantBits, ShiftLeft, ShiftRightArithmetic, ShiftRightLogical, Shuffle .
  • 为 Vector128/Vector256 补充向量方法: Abs, Add, AndNot, BitwiseAnd, BitwiseOr, ConditionalSelect, Divide, GreaterThan, LessThan, Max, Min, Multiply, Negate, OnesComplement, Subtract, Xor .
  • 提供限制的向量方法: YClamp .
  • 提供缩窄饱和的向量方法: YNarrowSaturate, YNarrowSaturateUnsigned .
  • 提供舍入的向量方法: YRoundToEven, YRoundToZero .
  • 提供换位的向量方法: YShuffleInsert, YShuffleKernel, YShuffleG2, YShuffleG4, YShuffleG4X2 . Also provides ShuffleControlG2/ShuffleControlG4 enum.

完整列表: ChangeLog

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值