文章目录
- 发布 VectorTraits v3.1(支持 .NET 9.0,支持 原生AOT)
- 支持 .NET 9.0
- 中断性变更
- 支持 原生AOT
- 原生AOT的范例
- 使用IlcInstructionSet参数
- TraitsOutput类增加IsDynamicCodeCompiled/IsDynamicCodeSupported信息的输出
- 为了支持原生AOT, 将ReflectionUtil等类的所有Type集合, 修改为 WrappedType 集合
- 附录
发布 VectorTraits v3.1(支持 .NET 9.0,支持 原生AOT)
VectorTraits已更新至 v3.1版。支持 .NET 9.0,支持 原生AOT。
- NuGet: https://www.nuget.org/packages/VectorTraits/3.1.0
- 源代码: https://github.com/zyl910/VectorTraits
- 在线文档: https://zyl910.github.io/VectorTraits_doc/
变更日志如下。
- Add TargetFrameworks
net9.0
(增加目标框架net9.0
): VectorTraits.dll. - Support for Native AOT (支持 原生AOT).
- The TraitsOutput class adds the output of this information (TraitsOutput类增加这些信息的输出): IsDynamicCodeCompiled, IsDynamicCodeSupported.
- Add WrappedType, WrappedTypePool classes. They are used to solve the problem of reflection in Native AOT. (增加 WrappedType, WrappedTypePool 类. 它们用于解决反射在原生AOT时的问题).
- To support Native AOT, modify all Type collections of ReflectionUtil and other classes to WrappedType collections (为了支持原生AOT, 将ReflectionUtil等类的所有Type集合, 修改为 WrappedType 集合).
完整列表: ChangeLog
支持 .NET 9.0
相关日志:
- Add TargetFrameworks
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版将彻底解决这一问题:
- 本库的 ConvertToInt64 将会改名为 ConvertToInt64Native。与 Vector 类在 .NET 9 新增的 ConvertToInt64Native 方法的保持一致。
- 本库还将增加 符合 .NET 9 饱和规则的 ConvertToInt64方法。注意本库还支持低版本的 .NET,所以即使在低版本 .NET下运行,本库也会按照 .NET 9 的新规则来处理。
且 ConvertToInt32 等其他的浮点数转整数的方法,也会按此改造。
且对于 .NET 9.0 新增的其他向量方法(如 Exp、Log、Sin……),本库的4.0版将支持它们。
支持 原生AOT
相关日志:
- Support for Native AOT (支持 原生AOT).
本库已经支持了 原生AOT。
原生AOT是从 .NET 7.0 开始提供的,.NET 8.0 才开始成熟。对于原生AOT的使用,可以参考 hez2010的文章: .NET NativeAOT 指南。
原生AOT的范例
现在以 VectorTraits.Sample
为例来介绍原生AOT的使用。
先使项目支持原生AOT。配置 VectorTraits.Sample.csproj
,加上“PublishAot”。
<PublishAot Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net7.0'))">true</PublishAot>
随后使用命令行,进行原生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.dllE:\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个警告。
- NETSDK1215:该警告不用理会。本库为了支持更多的 .NET 版本,于是使用了
.NET Standard 1.1
。而现在原生AOT编译用的是 net9.0,与它无关。 - IL2111:该警告不会影响程序的正常运行,可忽略。该警告是 net9.0 新增的警告,目前资料少,没有介绍消除办法。且该警告不会影响程序的正常运行,故可忽略。
随后去 bin\Release\net9.0\win-x64\publish\
文件夹找到打包后的程序,运行它。输出信息摘录如下。
VectorTraits.SampleIsRelease: 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<byte>.Count: 16 # 128bit
Vector<float>.Count: 4 # 128bit
Vector128.IsHardwareAccelerated: True
Vector256.IsHardwareAccelerated: False
Vector512.IsHardwareAccelerated: False
Vector<T>.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, Sse42src: <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参数
使用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.dllVectorTraits.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版将处理这一问题。
TraitsOutput类增加IsDynamicCodeCompiled/IsDynamicCodeSupported信息的输出
相关日志:
- The TraitsOutput class adds the output of this information (TraitsOutput类增加这些信息的输出): IsDynamicCodeCompiled, IsDynamicCodeSupported.
VectorTraits.Sample 等程序使用了TraitsOutput类输出了 .NET 环境信息。如今增加了这2项的输出:IsDynamicCodeCompiled, IsDynamicCodeSupported。
当未配置原生AOT发布时,这2个属性一般为 True。
当已配置原生AOT发布时,这2个属性一般为 False。故可以用它们来判断是否配置了原生AOT。
为了支持原生AOT, 将ReflectionUtil等类的所有Type集合, 修改为 WrappedType 集合
相关日志:
- Add WrappedType, WrappedTypePool classes. They are used to solve the problem of reflection in Native AOT. (增加 WrappedType, WrappedTypePool 类. 它们用于解决反射在原生AOT时的问题).
- To support Native AOT, modify all Type collections of ReflectionUtil and other classes to WrappedType collections (为了支持原生AOT, 将ReflectionUtil等类的所有Type集合, 修改为 WrappedType 集合).
本库内部使用了新增的 WrappedType, WrappedTypePool类型来解决 原生AOT的报错。这2个类是 public的,其他程序也可使用。
ReflectionUtil 及相关类型原本使用了 Type集合。现在为了支持原生AOT,已将参数类型改为 WrappedType集合了。这是一个中断性变更。ReflectionUtil主要是给测试使用的(如 VectorTraits.Benchmarks
、VectorTraits.Tests
),外部程序若使用了它们,需进行修正。
附录
参考资料:
- Microsoft .NET 9 中的中断性变更 - JIT 编译器 - 浮点数到整数转换将要饱和
- Microsoft Vector.ConvertToInt64Native(Vector) Method
- Microsoft Native AOT deployment
- hez2010 .NET NativeAOT 指南
以前的发布日志:
- 发布 VectorTraits v1.0, 它是C#下增强SIMD向量运算的类库
- 发布 VectorTraits v2.0(支持 X86的Sse系列指令集等)
- 发布 VectorTraits v3.0(支持 X86架构的Avx512系列指令集,支持 Wasm架构及PackedSimd指令集等)