VectorTraits已更新至 v3.1版。支持 .NET 9.0,支持 原生AOT。
变更日志如下。
net9.0
(增加目标框架 net9.0
): VectorTraits.dll.完整列表: ChangeLog
相关日志:
net9.0
(增加目标框架 net9.0
): VectorTraits.dll.本库已经增加了目标框架—— net9.0
。
除了 ConvertToInt64 等浮点数转整数的方法外,其他的单元测试均测试通过。
这是因为 .NET 9 的一个中断性变更: .NET 9 中的中断性变更 - JIT 编译器 - 浮点数到整数转换将要饱和
简单来说,.NET 9 将浮点数转整数规则修改为——若输入值超过整数的边界,结果会饱和到边界。且输入值为 NaN 时,结果会是0。
目前本库的 ConvertToInt64 等浮点数转整数的方法,仍然是按照旧版本(.NET Framework 1.1~4.8.1、.NET Core 1.0~ 8.0)的规则来处理的。于是在.NET 9 下,若输入值超过整数的边界,就与 Vector 类中对应方法的结果不一致了。
其实它的影响很小,因为仅当“输入值超过整数的边界”时才会不一致。而大多数严谨的程序会在 ConvertToInt64 之前检查数据范围,在范围内时才采用ConvertToInt64的结果。
本库的4.0版将彻底解决这一问题:
且 ConvertToInt32 等其他的浮点数转整数的方法,也会按此改造。
且对于 .NET 9.0 新增的其他向量方法(如 Exp、Log、Sin……),本库的4.0版将支持它们。
相关日志:
本库已经支持了 原生AOT。
原生AOT是从 .NET 7.0 开始提供的,.NET 8.0 才开始成熟。对于原生AOT的使用,可以参考 hez2010的文章: .NET NativeAOT 指南。
现在以 VectorTraits.Sample
为例来介绍原生AOT的使用。
先使项目支持原生AOT。配置 VectorTraits.Sample.csproj
,加上“PublishAot”。
<PublishAot Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net7.0'))">truePublishAot>
随后使用命令行,进行原生AOT打包。假设现在用的是Windows平台,于是打包目标是“win-x64”平台的。
打开终端,使用 cd命令进入 VectorTraits.Sample
的目录,随后使用下列命令进行AOT打包。
dotnet publish -c Release -r win-x64 -f net9.0
随后会输出以下信息。
C:\Program Files\dotnet\sdk\9.0.102\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.TargetFrameworkInference.targets(187,5): warning NETSDK1215: Targeting .NET Standard prior to 2.0 is no longer recommended. See https://aka.ms/dotnet/dotnet-standard-guidance for more details.
VectorTraits net9.0 succeeded with 2 warning(s) (46.9s) → E:\zylSelf\Code\cs\base\VectorTraits\src\VectorTraits\bin\Release\net9.0\VectorTraits.dll
E:\zylSelf\Code\cs\base\VectorTraits\src\VectorTraits\Impl\ReflectionUtil.cs(182,63): warning IL2111: Method 'Zyl.VectorTraits.Impl.ReflectionUtil.TypeInvokeGetIsSupported(Type)' with parameters or return value with `DynamicallyAccessedMembersAttribute` is accessed via reflection. Trimmer can't guarantee availability of the requirements of the method.
E:\zylSelf\Code\cs\base\VectorTraits\src\VectorTraits\Impl\ReflectionUtil.cs(136,48): warning IL2111: Method 'Zyl.VectorTraits.Impl.ReflectionUtil.TypeInvokeGetIsSupported(Type)' with parameters or return value with `DynamicallyAccessedMembersAttribute` is accessed via reflection. Trimmer can't guarantee availability of the requirements of the method.
VectorTraits.Sample net9.0 succeeded (112.7s) → bin\Release\net9.0\win-x64\publish\
Build succeeded with 2 warning(s) in 161.8s
打包成功了,只是有2个警告。
.NET Standard 1.1
。而现在原生AOT编译用的是 net9.0,与它无关。随后去 bin\Release\net9.0\win-x64\publish\
文件夹找到打包后的程序,运行它。输出信息摘录如下。
VectorTraits.Sample
IsRelease: True
Environment.ProcessorCount: 16
Environment.Is64BitProcess: True
Environment.OSVersion: Microsoft Windows NT 10.0.26100.0
Environment.Version: 9.0.1
Stopwatch.Frequency: 10000000
RuntimeFeature.IsDynamicCodeCompiled: False
RuntimeFeature.IsDynamicCodeSupported: False
RuntimeEnvironment.GetRuntimeDirectory: E:\zylSelf\Code\cs\base\VectorTraits\samples\VectorTraits.Sample\bin\Release\net9.0\win-x64\publish\
RuntimeInformation.FrameworkDescription: .NET 9.0.1
RuntimeInformation.OSArchitecture: X64
RuntimeInformation.OSDescription: Microsoft Windows 10.0.26100
RuntimeInformation.RuntimeIdentifier: win-x64
IntPtr.Size: 8
BitConverter.IsLittleEndian: True
Vector.IsHardwareAccelerated: True
Vector.Count: 16 # 128bit
Vector.Count: 4 # 128bit
Vector128.IsHardwareAccelerated: True
Vector256.IsHardwareAccelerated: False
Vector512.IsHardwareAccelerated: False
Vector.Assembly.CodeBase: CodeBase is not supported on assemblies loaded from a single-file bundle.
GetTargetFrameworkDisplayName(VectorTextUtil): .NET 9.0
GetTargetFrameworkDisplayName(TraitsOutput): .NET 9.0
VectorTraitsGlobal.InitCheckSum: -2122844161 # 0x8177F7FF
VectorEnvironment.CpuModelName: AMD Ryzen 7 7840H w/ Radeon 780M Graphics
VectorEnvironment.SupportedInstructionSets: Aes, Lzcnt, Pclmulqdq, Popcnt, Sse, Sse2, Sse3, Ssse3, Sse41, Sse42, X86Base
Vector128s.Instance: WVectorTraits128Sse // Sse, Sse2, Sse3, Ssse3, Sse41, Sse42
Vectors.Instance: VectorTraits128Sse // Sse, Sse2, Sse3, Ssse3, Sse41, Sse42
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
可见,程序正常运行了。
可以注意到,CodeBase的结果是一个错误信息—— CodeBase is not supported on assemblies loaded from a single-file bundle.
。
这是因为原生AOT发布后,不再支持该属性。也可从这个信息看出,该程序是原生AOT发布的。
另外还可以注意到,SupportedInstructionSets属性的结果不太正常。现在CPU是 “AMD Ryzen 7 7840H”,它支持AVX系列指令集的,但SupportedInstructionSets里没有。
这是因为原生AOT是提前生成机器码,它为了尽量避免老CPU不支持新指令集的问题,于是默认仅允许最基础的指令集。
使用IlcInstructionSet参数,可以配置原生AOT发布时所允许的指令集。最常见的参数是“native”,即使用当前CPU所支持的指令集。
在终端中执行以下命令。
dotnet publish -c Release -r win-x64 -f net9.0 /p:IlcInstructionSet=native
随后会输出以下信息。
C:\Program Files\dotnet\sdk\9.0.102\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.TargetFrameworkInference.targets(187,5): warning NETSDK1215: Targeting .NET Standard prior to 2.0 is no longer recommended. See https://aka.ms/dotnet/dotnet-standard-guidance for more details.
VectorTraits net9.0 succeeded (0.5s) → E:\zylSelf\Code\cs\base\VectorTraits\src\VectorTraits\bin\Release\net9.0\VectorTraits.dll
VectorTraits.Sample net9.0 succeeded (104.8s) → bin\Release\net9.0\win-x64\publish\
Build succeeded in 105.8s
打包成功了,随后我们运行程序。会发现这些信息与与之前的不同,该CPU的指令集均启用了。
VectorEnvironment.SupportedInstructionSets: Aes, Avx, Avx2, Avx512BW, Avx512CD, Avx512DQ, Avx512F, Avx512Vbmi, Avx512VL, Bmi1, Bmi2, Fma, Lzcnt, Pclmulqdq, Popcnt, Sse, Sse2, Sse3, Ssse3, Sse41, Sse42, X86Base
Vector128s.Instance: WVectorTraits128Avx2 // Sse, Sse2, Sse3, Ssse3, Sse41, Sse42, Avx, Avx2, Avx512VL
Vector256s.Instance: WVectorTraits256Avx2 // Avx, Avx2, Sse, Sse2, Avx512VL
Vector512s.Instance: WVectorTraits512Avx512 // Avx512BW, Avx512DQ, Avx512F, Avx512Vbmi, Avx, Avx2, Sse, Sse2
Vectors.Instance: VectorTraits256Avx2 // Avx, Avx2, Sse, Sse2, Avx512VL
原生AOT发布后,本库的“根据当前CPU动态选择最佳指令”的功能失效了,导致某些方法的向量硬件加速不及预期。本库的4.0版将处理这一问题。
相关日志:
VectorTraits.Sample 等程序使用了TraitsOutput类输出了 .NET 环境信息。如今增加了这2项的输出:IsDynamicCodeCompiled, IsDynamicCodeSupported。
当未配置原生AOT发布时,这2个属性一般为 True。
当已配置原生AOT发布时,这2个属性一般为 False。故可以用它们来判断是否配置了原生AOT。
相关日志:
本库内部使用了新增的 WrappedType, WrappedTypePool类型来解决 原生AOT的报错。这2个类是 public的,其他程序也可使用。
ReflectionUtil 及相关类型原本使用了 Type集合。现在为了支持原生AOT,已将参数类型改为 WrappedType集合了。这是一个中断性变更。ReflectionUtil主要是给测试使用的(如 VectorTraits.Benchmarks
、VectorTraits.Tests
),外部程序若使用了它们,需进行修正。
参考资料:
以前的发布日志: