发布 VectorTraits v3.1(支持 .NET 9.0,支持 原生AOT)

ops/2025/2/3 19:13:08/

文章目录

  • 发布 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.BenchmarksVectorTraits.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指令集等)

http://www.ppmy.cn/ops/155378.html

相关文章

39. I2C实验

一、IIC协议详解 1、ALPHA开发板上有个AP3216C&#xff0c;这是一个IIC接口的器件&#xff0c;这是一个环境光传感器。AP3216C连接到了I2C1上: I2C1_SCL: 使用的是UART4_TXD这个IO&#xff0c;复用位ALT2 I2C1_SDA: 使用的是UART4_RXD这个IO。复用为ALT2 2、I2C分为SCL和SDA&…

doris:主键模型的更新并发控制

概览​ Doris 采用多版本并发控制机制&#xff08;MVCC - Multi-Version Concurrency Control&#xff09;来管理并发更新。每次数据写入操作均会分配一个写入事务&#xff0c;该事务确保数据写入的原子性&#xff08;即写入操作要么完全成功&#xff0c;要么完全失败&#xf…

数组—学习

1.基础知识 1. 高精度计算 高精度算法是处理大数&#xff08;超过64位&#xff09;的计算方法。C标准库没有直接支持大数运算&#xff0c;因此需要使用数组来模拟大数的存储和运算。 2. 全局静态数组 全局变量&#xff08;包括静态数组&#xff09;在C中会在程序启动时自动初…

GWO优化LSBooST回归预测matlab

灰狼优化算法&#xff08;Grey Wolf Optimizer&#xff0c;简称 GWO&#xff09;&#xff0c;是一种群智能优化算法&#xff0c;由澳大利亚格里菲斯大学的 Mirjalii 等人于 2014 年提出。该算法的设计灵感源自灰狼群体的捕食行为&#xff0c;核心思想是模仿灰狼社会的结构与行为…

「全网最细 + 实战源码案例」设计模式——享元模式

核心思想 享元模式&#xff08;Flyweight Pattern&#xff09;是一种结构型设计模式&#xff0c;主要用于减少程序中大量对象的内存消耗。该模式通过共享相同的数据来有效减少内存的使用&#xff0c;适用于对象非常多且可以共享一部分状态的场景。核心&#xff1a;将对象的内部…

小程序-基础加强-自定义组件

前言 这次讲自定义组件 1. 准备今天要用到的项目 2. 初步创建并使用自定义组件 这样就成功在home中引入了test组件 在json中引用了这个组件才能用这个组件 现在我们来实现全局引用组件 在app.json这样使用就可以了 3. 自定义组件的样式 发现页面里面的文本和组件里面的文…

STM32 旋转编码器

旋转编码器简介 旋转编码器&#xff1a;用来测量位置、速度或旋转方向的装置&#xff0c;当其旋转轴旋转时&#xff0c;其输出端可以输出与旋转速度和方向对应的方波信号&#xff0c;读取方波信号的频率和相位信息即可得知旋转轴的速度和方向 类型&#xff1a;机械触点式/霍尔传…

pandas(三)Series使用

一、Series基础使用 import pandasd {x:100,y:200,z:300} s1 pandas.Series(d) #将dict转化为Series print(s1)print("") l1 [1, 2, 3] l2 [a, b, c] s2 pandas.Series(l1, indexl2) #list转为Series print(s2)print("") s3 pandas.Series([11…