發佈 VectorTraits v2.0(支持 x86的Sse系列指令集等)

来源:https://www.cnblogs.com/zyl910/p/18078844/dotnet_dll_VectorTraits_v2_0
-Advertisement-
Play Games

本章將和大家分享如何通過 Elasticsearch 實現自動補全查詢功能。 一、自動補全-安裝拼音分詞器 1、自動補全需求說明 當用戶在搜索框輸入字元時,我們應該提示出與該字元有關的搜索項,如圖: 2、使用拼音分詞 要實現根據字母做補全,就必須對文檔按照拼音分詞。在 GitHub 上恰好有 Ela ...


目錄

VectorTraits已更新至 v2.0版。支持 x86的Sse系列指令集; 為 Vector128/Vector256 補充全部的向量方法; 還提供了 浮點數判斷(YIsNaN, YIsinfinity)、符號判斷(YCopySign, YSign) 等原創的向量方法。

變更日誌如下。

  • Major: Support for the X86 Sse family instruction set; supplement all vector methods for Vector128/Vector256; also provides innovative vector methods such as check floating number (YIsNaN, YIsInfinity), sign (YCopySign, YSign) (支持 x86的Sse系列指令集; 為 Vector128/Vector256 補充全部的向量方法; 還提供了 浮點數判斷(YIsNaN, YIsinfinity)、符號判斷(YCopySign, YSign) 等原創的向量方法).
  • Provides the CPU model info (提供CPU型號信息). VectorEnvironment adds members: CpuModelName, CpuFlags, CpuDetectionCommand, CpuDetectionException, CpuDetectionResult .
  • Provides information about the supported instruction set (提供所支持的指令集信息). e.g. VectorEnvironment.SupportedInstructionSets, IBaseTraits.UsedInstructionSets
  • Supplement all vector methods for Vector128/Vector256 (為 Vector128/Vector256 補充全部的向量方法): Dot, Equals, EqualsAll, EqualsAny, GreaterThanAll, GreaterThanAny, GreaterThanOrEqual, GreaterThanOrEqualAll, GreaterThanOrEqualAny, LessThanAll, LessThanAny, LessThanOrEqual, LessThanOrEqualAll, LessThanOrEqualAny, Sqrt .
  • Provides the vector methods of bitwise operations (提供位運算的向量方法): YBitToByte, YBitToInt16, YBitToInt32, YBitToInt64, YOrNot .
  • Provides the vector methods of check floating number (提供浮點數判斷的向量方法): YIsEvenInteger, YIsFinite, YIsInfinity, YIsInfinityOrNaN, YIsInteger, YIsNaN, YIsNegative, YIsNegativeZero, YIsNegativeInfinity, YIsNormal, YIsNotNaN, YIsOddInteger, YIsPositive, YIsPositiveInfinity, YIsSubnormal, YIsZero, YIsZeroOrSubnormal.
  • Provides the vector methods of check sign (提供符號判斷的向量方法): YCopySign, YSign, YSignFloat .
  • Provides the vector methods of clamp (提供限制的向量方法): YMaxNumber, YMinNumber .
  • Provides the vector methods of compare (提供比較的向量方法): YIsAllTrue, YIsAnyTrue, YIsNotEquals.
  • VectorTraits.dll: Add TargetFrameworks net8.0 and netstandard2.1 (增加目標框架 net8.0netstandard2.1 ).
  • Provides arrays of fixed length (提供固定長度的數組). e.g. FixedArray2, FixedArray4 ...
  • BitMath changed from static to abstract class. Add namespace Zyl.VectorTraits.Numerics, add some math functions (BitMath從靜態類改為抽象類. 新增名稱空間 Zyl.VectorTraits.Numerics, 增加一些的數學函數).
  • Benchmark programs add command line parameter (基準測試程式增加命令行參數): -accelerated0 -allowFakeBenchmark -cpuDetection0 -fixedVector0 -test0
  • Add tool program (增加工具程式): UpdateBenchmarkResults.
  • Optimized hardware acceleration of ExtractMostSignificantBits methods in the Arm architecture (優化ExtractMostSignificantBits方法在Arm架構的硬體加速). For 8~64 bit types.

完整列表: ChangeLog

支持 x86的Sse系列指令集

本庫已經支持了x86架構的Sse系列指令集。既:Sse, Sse2, Sse3, Ssse3, Sse41, Sse42。
在X86架構上使用128位向量(Vector128、128位時的Vector)時,現在能充分獲得硬體加速。

為 Vector128/Vector256 補充全部的向量方法

相關日誌:

  • Supplement all vector methods for Vector128/Vector256 (為 Vector128/Vector256 補充全部的向量方法): Dot, Equals, EqualsAll, EqualsAny, GreaterThanAll, GreaterThanAny, GreaterThanOrEqual, GreaterThanOrEqualAll, GreaterThanOrEqualAny, LessThanAll, LessThanAny, LessThanOrEqual, LessThanOrEqualAll, LessThanOrEqualAny, Sqrt .

對於固定長度的向量類型(Vector128/Vector256),在v1.0版時只是提供了常用的向量方法。
而現在v2.0版,已經補充全部的向量方法。已經覆蓋了 .NET 7.0中所有運算類的向量方法。例如 Dot, Equals, EqualsAll, EqualsAny 等.

這些向量方法的清單如下。

  • Dot①: Computes the dot product of two vectors (計算兩個向量的點積).
    Mnemonic: rt := left[0]*right[0] + left[1]*right[1] + left[2]*right[2] + ... + left[Count-1]*right[Count-1] .
  • Equals: Compares two vectors to determine if they are equal on a per-element basis (比較兩個向量,確定它們每個元素是否相等).
    Mnemonic: rt[i] := to_mask(left[i] == right[i]).
  • EqualsAll: Compares two vectors to determine if all elements are equal (比較兩個向量以判定所有元素是否相等).
    Mnemonic: rt := (left[0] == right[0]) && (left[1] == right[1]) && ... && (left[Count-1] == right[Count-1]).
  • EqualsAny: Compares two vectors to determine if any elements are equal (比較兩個向量以判定任一元素是否相等).
    Mnemonic: rt := (left[0] == right[0]) || (left[1] == right[1]) || ... || (left[Count-1] == right[Count-1]).
  • GreaterThanAll: Compares two vectors to determine if all elements are greater (比較兩個向量以判定所有元素是否大於).
    Mnemonic: rt := (left[0] > right[0]) && (left[1] > right[1]) && ... && (left[Count-1] > right[Count-1]).
  • GreaterThanAny: Compares two vectors to determine if any elements are greater (比較兩個向量以判定任一元素是否大於).
    Mnemonic: rt := (left[0] > right[0]) || (left[1] > right[1]) || ... || (left[Count-1] > right[Count-1]).
  • GreaterThanOrEqual: Compares two vectors to determine which is greater or equal on a per-element basis (比較兩個向量,在每個元素的基礎上確定哪個更大或等於).
    Mnemonic: rt[i] := to_mask(left[i] >= right[i]).
  • GreaterThanOrEqualAll: Compares two vectors to determine if all elements are greater or equal (比較兩個向量以判定所有元素是否大於或等於).
    Mnemonic: rt := (left[0] >= right[0]) && (left[1] >= right[1]) && ... && (left[Count-1] >= right[Count-1]).
  • GreaterThanOrEqualAny: Compares two vectors to determine if any elements are greater or equal (比較兩個向量以判定任一元素是否大於或等於).
    Mnemonic: rt := (left[0] >= right[0]) || (left[1] >= right[1]) || ... || (left[Count-1] >= right[Count-1]).
  • LessThanAll: Compares two vectors to determine if all elements are less (比較兩個向量以判定所有元素是否小於).
    Mnemonic: rt := (left[0] < right[0]) && (left[1] < right[1]) && ... && (left[Count-1] < right[Count-1]).
  • LessThanAny: Compares two vectors to determine if any elements are less (比較兩個向量以判定任一元素是否小於).
    Mnemonic: rt := (left[0] < right[0]) || (left[1] < right[1]) || ... || (left[Count-1] < right[Count-1]).
  • LessThanOrEqual: Compares two vectors to determine which is less or equal on a per-element basis (比較兩個向量,在每個元素的基礎上確定哪個更小或等於).
    Mnemonic: rt[i] := to_mask(left[i] <= right[i]).
  • LessThanOrEqualAll: Compares two vectors to determine if all elements are less or equal (比較兩個向量以判定所有元素是否小於或等於).
    Mnemonic: rt := (left[0] <= right[0]) && (left[1] <= right[1]) && ... && (left[Count-1] <= right[Count-1]).
  • LessThanOrEqualAny: Compares two vectors to determine if any elements are less or equal (比較兩個向量以判定任一元素是否小於或等於).
    Mnemonic: rt := (left[0] <= right[0]) || (left[1] <= right[1]) || ... || (left[Count-1] <= right[Count-1]).
  • Sqrt①: Computes the square root of a vector on a per-element basis (計算向量中每個元素的平方根).
    Mnemonic: rt[i] := sqrt(vector[i]) = pow(vector[i], 1.0/2). When x is less than 0, floating-point types return NaN, integer types return 0.

註:①表示這些方法也適用於不定長度的向量類型Vector. 因發現Vector的這些方法中, 部分元素類型沒能提供硬體加速。

提供CPU型號信息

相關日誌:

  • Provides the CPU model info (提供CPU型號信息). VectorEnvironment adds members: CpuModelName, CpuFlags, CpuDetectionCommand, CpuDetectionException, CpuDetectionResult .

在使用向量方法時,很多時候我們想知道CPU型號信息,但BCL未提供辦法。於是v2.0版提供了查看CPU型號信息的屬性,且支持 Windows/Linux/Mac 這3大主流操作系統。

VectorEnvironment類提供了這些成員。

  • CpuModelName: CPU型號名。例如 Intel(R) Core(TM) i5-8250U CPU @ 1.60GHz, Neoverse-N1
  • CpuFlags: CPU特征標誌。目前僅Linux操作系統上有值,它就是lscpu命令所返回的flags欄位。例如Neoverse-N1的該屬性為 fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop asimddp ssbs.
  • CpuDetectionCommand: CPU檢測所用命令。不同操作系統(Windows/Linux/Mac)上,所用的命令不同。例如wmic
  • CpuDetectionException: CPU檢測時的最新異常。
  • CpuDetectionResult: CPU檢測的原始返回值. 它與 CpuDetectionCommand 有關。

一般情況下直接使用VectorEnvironment的屬性就行。範例代碼如下。

writer.WriteLine("CpuModelName: {0}", VectorEnvironment.CpuModelName);
writer.WriteLine("CpuFlags: {0}", VectorEnvironment.CpuFlags);
writer.WriteLine("CpuDetectionException: {0}", VectorEnvironment.CpuDetectionException);
writer.WriteLine("CpuDetectionCommand: {0}", VectorEnvironment.CpuDetectionCommand);
writer.Write("CpuDetectionResult:\t");
VectorTextUtil.WriteLines(writer, VectorEnvironment.CpuDetectionResult);
writer.WriteLine();

只有有一種情況需要特殊處理。就是在 .NET Framework 4.5等低版本(低於.NET Framework 4.6.1)程式里使用本庫時,此時使用的是 netstandard1.1的庫,而 netstandard1.1未提供 System.Diagnostics.Process 類,會導致無法獲取CPU信息的情況。
解決辦法是是提前將 System.Diagnostics.Process 的類型賦值給一個屬性。隨後本庫便可通過反射來使用該類,從而能正常獲取CPU信息了。範例代碼如下。

#if NETSTANDARD1_3_OR_GREATER || NETCOREAPP2_0_OR_GREATER || NET461_OR_GREATER
    // No need to set up `ProcessUtil.TypeOfProcess` properties. 
#else
    Zyl.VectorTraits.Impl.Util.ProcessUtil.TypeOfProcess = typeof(System.Diagnostics.Process);
#endif

結果範例1: X86 CPU on Windows

CpuModelName: Intel(R) Core(TM) i5-8250U CPU @ 1.60GHz
CpuFlags: 
CpuDetectionException:
CpuDetectionCommand: wmic


AddressWidth=64
Architecture=9
AssetTag=None
Availability=3
Caption=Intel64 Family 6 Model 142 Stepping 10
Characteristics=252
ConfigManagerErrorCode=
ConfigManagerUserConfig=
CpuStatus=1
CreationClassName=Win32_Processor
CurrentClockSpeed=1600
CurrentVoltage=11
DataWidth=64
Description=Intel64 Family 6 Model 142 Stepping 10
DeviceID=CPU0
ErrorCleared=
ErrorDescription=
ExtClock=100
Family=205
InstallDate=
L2CacheSize=1024
L2CacheSpeed=
L3CacheSize=6144
L3CacheSpeed=0
LastErrorCode=
Level=6
LoadPercentage=7
Manufacturer=GenuineIntel
MaxClockSpeed=1800
Name=Intel(R) Core(TM) i5-8250U CPU @ 1.60GHz
NumberOfCores=4
NumberOfEnabledCore=4
NumberOfLogicalProcessors=8
OtherFamilyDescription=
PartNumber=None
PNPDeviceID=
PowerManagementCapabilities=
PowerManagementSupported=FALSE
ProcessorId=BFEBFBFF000806EA
ProcessorType=3
Revision=
Role=CPU
SecondLevelAddressTranslationExtensions=TRUE
SerialNumber=None
SocketDesignation=U3E1
Status=OK
StatusInfo=3
Stepping=
SystemCreationClassName=Win32_ComputerSystem
SystemName=THINK1621
ThreadCount=8
UniqueId=
UpgradeMethod=51
Version=
VirtualizationFirmwareEnabled=TRUE
VMMonitorModeExtensions=TRUE
VoltageCaps=

結果範例2: Arm CPU on Linux

CpuModelName: Neoverse-N1
CpuFlags: fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop asimddp ssbs
CpuDetectionException: 
CpuDetectionCommand: lscpu
Architecture:                    aarch64
CPU op-mode(s):                  32-bit, 64-bit
Byte Order:                      Little Endian
CPU(s):                          2
On-line CPU(s) list:             0,1
Vendor ID:                       ARM
Model name:                      Neoverse-N1
Model:                           1
Thread(s) per core:              1
Core(s) per socket:              2
Socket(s):                       1
Stepping:                        r3p1
BogoMIPS:                        243.75
Flags:                           fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop asimddp ssbs
L1d cache:                       128 KiB (2 instances)
L1i cache:                       128 KiB (2 instances)
L2 cache:                        2 MiB (2 instances)
L3 cache:                        32 MiB (1 instance)
NUMA node(s):                    1
NUMA node0 CPU(s):               0,1
Vulnerability Itlb multihit:     Not affected
Vulnerability L1tf:              Not affected
Vulnerability Mds:               Not affected
Vulnerability Meltdown:          Not affected
Vulnerability Mmio stale data:   Not affected
Vulnerability Retbleed:          Not affected
Vulnerability Spec store bypass: Mitigation; Speculative Store Bypass disabled via prctl
Vulnerability Spectre v1:        Mitigation; __user pointer sanitization
Vulnerability Spectre v2:        Mitigation; CSV2, BHB
Vulnerability Srbds:             Not affected
Vulnerability Tsx async abort:   Not affected

結果範例3: Arm CPU on Mac OS

CpuModelName: Apple M2
CpuFlags: 
CpuDetectionException: 
CpuDetectionCommand: sysctl
kern.sched_rt_avoid_cpu0: 0
kern.cpu_checkin_interval: 4000
hw.ncpu: 8
hw.activecpu: 8
hw.perflevel0.physicalcpu: 4
hw.perflevel0.physicalcpu_max: 4
hw.perflevel0.logicalcpu: 4
hw.perflevel0.logicalcpu_max: 4
hw.perflevel0.cpusperl2: 4
hw.perflevel1.physicalcpu: 4
hw.perflevel1.physicalcpu_max: 4
hw.perflevel1.logicalcpu: 4
hw.perflevel1.logicalcpu_max: 4
hw.perflevel1.cpusperl2: 4
hw.physicalcpu: 8
hw.physicalcpu_max: 8
hw.logicalcpu: 8
hw.logicalcpu_max: 8
hw.cputype: 16777228
hw.cpusubtype: 2
hw.cpu64bit_capable: 1
hw.cpufamily: -634136515
hw.cpusubfamily: 2
machdep.cpu.cores_per_package: 8
machdep.cpu.core_count: 8
machdep.cpu.logical_per_package: 8
machdep.cpu.thread_count: 8
machdep.cpu.brand_string: Apple M2

提供所支持的指令集信息

相關日誌:

  • Provides information about the supported instruction set (提供所支持的指令集信息). e.g. VectorEnvironment.SupportedInstructionSets, IBaseTraits.UsedInstructionSets

有了這些屬性後,便能查看所支持的指令集了。

  • VectorEnvironment類提供了SupportedInstructionSets屬性。用於獲取本機所支持的指令。
  • 許多類型(Vectors、Vector128s、Vector256s與IBaseTraits的派生類)提供了UsedInstructionSets屬性。用於獲取該向量類型所使用的指令。

註:多個指令集時,會使用分隔符。分隔符是逗號 ','。

結果範例1: X86 CPU on Windows

VectorEnvironment.CpuModelName:	Intel(R) Core(TM) i5-8250U CPU @ 1.60GHz
VectorEnvironment.SupportedInstructionSets:	Aes, Avx, Avx2, Bmi1, Bmi2, Fma, Lzcnt, Pclmulqdq, Popcnt, Sse, Sse2, Sse3, Ssse3, Sse41, Sse42, X86Base
Vector128s.Instance:	WVectorTraits128Avx2	// Sse, Sse2, Sse3, Ssse3, Sse41, Sse42, Avx, Avx2
Vector256s.Instance:	WVectorTraits256Avx2	// Avx, Avx2, Sse, Sse2
Vectors.Instance:	VectorTraits256Avx2	// Avx, Avx2, Sse, Sse2

註:“//” 後面的就是UsedInstructionSets屬性的值。

結果範例2: Arm CPU on Linux

VectorEnvironment.CpuModelName:	Neoverse-N1
VectorEnvironment.CpuFlags:	fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop asimddp ssbs
VectorEnvironment.SupportedInstructionSets:	AdvSimd, Aes, ArmBase, Crc32, Sha1, Sha256
Vector128s.Instance:	WVectorTraits128AdvSimdB64	// AdvSimd
Vectors.Instance:	VectorTraits128AdvSimdB64	// AdvSimd

結果範例3: Arm CPU on Mac OS

VectorEnvironment.CpuModelName:	Apple M2
VectorEnvironment.SupportedInstructionSets:	AdvSimd, Aes, ArmBase, Crc32, Dp, Rdm, Sha1, Sha256
Vector128s.Instance:	WVectorTraits128AdvSimdB64	// AdvSimd
Vectors.Instance:	VectorTraits128AdvSimdB64	// AdvSimd

新增了向量方法

相關日誌:

  • Provides the vector methods of bitwise operations (提供位運算的向量方法): YBitToByte, YBitToInt16, YBitToInt32, YBitToInt64, YOrNot .
  • Provides the vector methods of check floating number (提供浮點數判斷的向量方法): YIsEvenInteger, YIsFinite, YIsInfinity, YIsInfinityOrNaN, YIsInteger, YIsNaN, YIsNegative, YIsNegativeZero, YIsNegativeInfinity, YIsNormal, YIsNotNaN, YIsOddInteger, YIsPositive, YIsPositiveInfinity, YIsSubnormal, YIsZero, YIsZeroOrSubnormal.
  • Provides the vector methods of check sign (提供符號判斷的向量方法): YCopySign, YSign, YSignFloat .
  • Provides the vector methods of clamp (提供限制的向量方法): YMaxNumber, YMinNumber .
  • Provides the vector methods of compare (提供比較的向量方法): YIsAllTrue, YIsAnyTrue, YIsNotEquals.

位運算的向量方法

  • YBitToByte: Converts binary bits to each element of the Byte vector (將各個二進位位轉換為 Byte 向量的每個元素). Bit 0 meaning is 0, bit 1 meaning is 1 for all bits (byte.MaxValue).
    Mnemonic: rt[i] := to_mask(0 != ((value>>i)&1)) .
  • YBitToInt16: Converts binary bits to each element of the Int16 vector (將各個二進位位轉換為 Int16 向量的每個元素). Bit 0 meaning is 0, bit 1 meaning is 1 for all bits (-1).
    Mnemonic: rt[i] := to_mask(0 != ((value>>i)&1)) .
  • YBitToInt32: Converts binary bits to each element of the Int32 vector (將各個二進位位轉換為 Int32 向量的每個元素). Bit 0 meaning is 0, bit 1 meaning is 1 for all bits (-1).
    Mnemonic: rt[i] := to_mask(0 != ((value>>i)&1)) .
  • YBitToInt64: Converts binary bits to each element of the Int64 vector (將各個二進位位轉換為 Int64 向量的每個元素). Bit 0 meaning is 0, bit 1 meaning is 1 for all bits (-1).
    Mnemonic: rt[i] := to_mask(0 != ((value>>i)&1)) .

註:YBitToByte 等方法,是 ExtractMostSignificantBits 方法的逆運算。

浮點數判斷的向量方法

  • YIsEvenInteger: Determines if a element represents an even integral number (確定元素是否為偶數整數).
    Mnemonic: rt[i] := to_mask(isEvenInteger(value[i])) .
  • YIsFinite: Determines if a element is finite. It contains zero, subnormal, and normal. It does not contain infinity, NaN (確定元素是否為有限值. 它包含 零、次正規數、正規數. 它不含無窮大、非數).
    Mnemonic: rt[i] := to_mask(isFinite(value[i])) .
  • YIsInfinity: Determines if a element is infinite (確定元素是否為無窮大).
    Mnemonic: rt[i] := to_mask(isInfinity(value[i])) .
  • YIsInfinityOrNaN: Determines if a element is infinite or NaN (確定元素是否為無窮大或非數).
    Mnemonic: rt[i] := to_mask(isInfinityOrNaN(value[i])) .
  • YIsInteger: Determines if a element represents an integral number (確定元素是否為整數).
    Mnemonic: rt[i] := to_mask(isInteger(value[i])) .
  • YIsNaN: Determines if a element is NaN (確定元素是否為非數).
    Mnemonic: rt[i] := to_mask(isNaN(value[i])) .
  • YIsNegative: Determines if a element represents a negative number or negative zero (確定元素是否為負數或負零).
    Mnemonic: rt[i] := to_mask(isNegative(value[i])) = to_mask((value[i]<0) || isNegativeZero(value[i])) .
  • YIsNegativeInfinity: Determines if a element is negative infinity (確定元素是否為負無窮大).
    Mnemonic: rt[i] := to_mask(isNegativeInfinity(value[i])) .
  • YIsNegativeZero: Determines if a element represents a negative zero (確定元素是否為負零).
    Mnemonic: rt[i] := to_mask(isNegativeZero(value[i])) .
  • YIsNormal: Determines if a element is normal (確定元素是否為正規數).
    Mnemonic: rt[i] := to_mask(isNormal(value[i])) .
  • YIsNotNaN: Determines if a element is not NaN (確定元素是否不為非數).
    Mnemonic: rt[i] := to_mask(isNotNaN(value[i])) = to_mask(!isNaN(value[i])) .
  • YIsOddInteger: Determines if a element represents an odd integral number (確定元素是否為奇數整數).
    Mnemonic: rt[i] := to_mask(isOddInteger(value[i])) .
  • YIsPositive: Determines if a element represents zero or a positive number (確定元素是否為零或正數).
    Mnemonic: rt[i] := to_mask(isPositive(value[i])) .
  • YIsPositiveInfinity: Determines if a element is positive infinity (確定元素是否為正無窮大).
    Mnemonic: rt[i] := to_mask(isPositiveInfinity(value[i])) .
  • YIsSubnormal: Determines if a element is subnormal (確定元素是否為次正規數).
    Mnemonic: rt[i] := to_mask(isSubnormal(value[i])) .
  • YIsZero: Determines if a element is zero (確定元素是否為零).
    Mnemonic: rt[i] := to_mask(0==value[i]) .
  • YIsZeroOrSubnormal: Determines if a element is zero or subnormal (確定元素是否為零或次正規數).
    Mnemonic: rt[i] := to_mask(isZeroOrSubnormal(value[i])) .

符號判斷的向量方法

  • YCopySign: Copies the sign of a value to the sign of another value (將一個值的符號複製到另一個值).
    Mnemonic: rt[i] := copySign(value[i], sign[i]).
  • YSign: Determine the sign of each element (判斷各個元素的符號). 其元素取決於value的對應元素的符號情況: 值為正數時返回1, 值為0或NaN時返回0, 值為負數時返回-1.
    Mnemonic: rt[i] := sign(value[i]).
  • YSignFloat: Determine the sign of each element and returns a floating point number (判斷各個元素的符號並返回浮點數). 其元素取決於value的對應元素的符號情況: 值為正數時返回1, 值為0時返回0, 值為負數時返回-1, 值為NaN時返回NaN.
    Mnemonic: rt[i] := signFloat(value[i]).

限制的向量方法

  • YMaxNumber: Computes the maximum number of two vectors on a per-element basis (在每個元素的基礎上計算兩個向量的最大數值). The maxNumber method matches the IEEE 754:2019 maximumNumber function. This requires NaN inputs to not be propagated back to the caller and for -0.0 to be treated as less than +0.0 (maxNumber方法與 IEEE 754:2019 maximumNumber 函數匹配。 這要求 NaN 輸入不傳播回調用方,且 -0.0 被視為小於 +0.0).
    Mnemonic: `rt[i] := maxNumber(left[i], right[i]).
  • YMinNumber: Computes the minimum number of two vectors on a per-element basis (在每個元素的基礎上計算兩個向量的最小數值). The minNumber method matches the IEEE 754:2019 minimumNumber function. This requires NaN inputs to not be propagated back to the caller and for -0.0 to be treated as less than +0.0 (minNumber方法與 IEEE 754:2019 minimumNumber 函數匹配。 這要求 NaN 輸入不傳播回調用方,且 -0.0 被視為小於 +0.0).
    Mnemonic: `rt[i] := minNumber(left[i], right[i]).

比較的向量方法

  • YIsAllTrue: Checks if all elements of the vector is true (檢查向量中所有元素是不是都為true).
    Mnemonic: rt := value[0] && value[1] && value[2] && ... && value[Count-1] . The element of value must be 0 or AllBitsSet (Signed integer value -1).
  • YIsAnyTrue: Checks if any elements of the vector is true (檢查向量中任一元素是不是為true).
    Mnemonic: rt := value[0] || value[1] || value[2] || ... || value[Count-1] . The element of value must be 0 or AllBitsSet (Signed integer value -1).
  • YIsNotEquals: Compares two vectors to determine if they are not equal on a per-element basis (比較兩個向量,確定它們每個元素是否不相等).
    Mnemonic: rt[i] := to_mask(left[i] != right[i]).

增加目標框架 net8.0netstandard2.1

相關日誌:

  • VectorTraits.dll: Add TargetFrameworks net8.0 and netstandard2.1 (增加目標框架 net8.0netstandard2.1 ).

本庫增加目標框架—— net8.0netstandard2.1。能更好的利用這些目標框架的一些新的方法來優化性能。
對於net8.0 新增的512位向量(Vector512)與Avx512指令集,本庫的3.0版將支持它們。

提供固定長度的數組

相關日誌:

  • Provides arrays of fixed length (提供固定長度的數組). e.g. FixedArray2, FixedArray4 ...

這一項功能主要是給本庫使用的。Unsafe.Add的地址計算,存在寫法繁瑣,很難利用“寄存器相對定址”、“相對基址變址定址”指令問題。
使用“固定長度的數組”後,能解決這些問題,且具有編譯時範圍檢查。
“固定長度的數組”的原理比較簡單,就是利用值類型的結構體的一些特點。將數組下標定址,換成訪問結構體的成員。當數組下標是常數時,使用“固定長度的數組”會更方便。

“固定長度的數組”的範例

例如下麵是一個計算float的256位向量相等(Vector256.Equals<float>)的函數。

public static Vector256<float> Equals_Basic(Vector256<float> left, Vector256<float> right) {
    UnsafeUtil.SkipInit(out Vector256<float> rt);
    ref int prt = ref Unsafe.As<Vector256<float>, int>(ref rt);
    ref float pleft = ref Unsafe.As<Vector256<float>, float>(ref left);
    ref float pright = ref Unsafe.As<Vector256<float>, float>(ref right);
    prt = BitMath.ToInt32Mask(pleft == pright);
    Unsafe.Add(ref prt, 1) = BitMath.ToInt32Mask(Unsafe.Add(ref pleft, 1) == Unsafe.Add(ref pright, 1));
    Unsafe.Add(ref prt, 2) = BitMath.ToInt32Mask(Unsafe.Add(ref pleft, 2) == Unsafe.Add(ref pright, 2));
    Unsafe.Add(ref prt, 3) = BitMath.ToInt32Mask(Unsafe.Add(ref pleft, 3) == Unsafe.Add(ref pright, 3));
    Unsafe.Add(ref prt, 4) = BitMath.ToInt32Mask(Unsafe.Add(ref pleft, 4) == Unsafe.Add(ref pright, 4));
    Unsafe.Add(ref prt, 5) = BitMath.ToInt32Mask(Unsafe.Add(ref pleft, 5) == Unsafe.Add(ref pright, 5));
    Unsafe.Add(ref prt, 6) = BitMath.ToInt32Mask(Unsafe.Add(ref pleft, 6) == Unsafe.Add(ref pright, 6));
    Unsafe.Add(ref prt, 7) = BitMath.ToInt32Mask(Unsafe.Add(ref pleft, 7) == Unsafe.Add(ref pright, 7));
    return rt;
}

說明一下,它是一個用標量演算法實現函數,用於在不支持向量指令時進行回退。所以需要分別對每一個元素來做相等比較,並將比較結果轉為掩碼。
float是32位的,256位向量里能放下8個float。於是上面的代碼使用Unsafe.Add,分別對8個元素進行了計算。

下麵是使用“固定長度的數組”改寫後的代碼。

public static Vector256<float> Equals_Basic(Vector256<float> left, Vector256<float> right) {
    UnsafeUtil.SkipInit(out Vector256<float> rt);
    ref FixedArray8<int> p = ref Unsafe.As<Vector256<float>, FixedArray8<int>>(ref rt);
    ref FixedArray8<float> pleft = ref Unsafe.As<Vector256<float>, FixedArray8<float>>(ref left);
    ref FixedArray8<float> pright = ref Unsafe.As<Vector256<float>, FixedArray8<float>>(ref right);
    p.I0 = BitMath.ToInt32Mask(pleft.I0 == pright.I0);
    p.I1 = BitMath.ToInt32Mask(pleft.I1 == pright.I1);
    p.I2 = BitMath.ToInt32Mask(pleft.I2 == pright.I2);
    p.I3 = BitMath.ToInt32Mask(pleft.I3 == pright.I3);
    p.I4 = BitMath.ToInt32Mask(pleft.I4 == pright.I4);
    p.I5 = BitMath.ToInt32Mask(pleft.I5 == pright.I5);
    p.I6 = BitMath.ToInt32Mask(pleft.I6 == pright.I6);
    p.I7 = BitMath.ToInt32Mask(pleft.I7 == pright.I7);
    return rt;
}

可見,擺脫了冗長的Unsafe.Add後,代碼簡潔了很多。
FixedArray8等“固定長度的數組”是結構體,且元素類型也是值類型,故它可以安全使用Unsafe.As來轉換引用的類型,從而直接操作變數的記憶體。

備註:定址方式說明

X86架構支持2種相對定址。資料摘錄如下。

寄存器相對定址方式
格式:操作碼 寄存器,DISP+基址或變址寄存器
有效地址=寄存器+8/16位相對值DISP
MOV AX, [SI+06H] ;AX←DS:[SI+06H]
MOV AX, 06H[SI] ;AX←DS:[SI+06H]

相對基址變址定址方式
格式:操作碼 寄存器,DISP+(基址寄存器)+(變址寄存器)
有效地址=BX/BP+SI/DI+8/16位相對值DISP
MOV AX, [BX+DI+6] ;AX←DS:[BX+DI+6]
MOV AX, 6[BX+DI] ; MOV AX, 6[BX][DI]

相對值DISP,是立即數(Immediate)。如上面範例里的6(或06H),它會直接編譯到機器碼里。
當使用這2種相對定址時,能在同一指令內就能完成“地址計算”與實際的“數據搬運”。
而不使用它們時,得花3條指令才能達到同樣的效果。分別是 “將立即數載入到寄存器”(相對值)、“加法”(基址+相對值)、“寄存器間接定址”。
目前發現直至.NET8.0,Unsafe.Add的地址計算代碼在JIT編譯為機器碼運行時,不會使用相對定址。即原本1條指令就能定址,但JIT只會編譯為3條指令的,影響了性能。
於是本庫使用“固定長度的數組”來解決這一性能問題。

BitMath從靜態類改為抽象類. 新增名稱空間 Zyl.VectorTraits.Numerics

相關日誌:

  • BitMath changed from static to abstract class. Add namespace Zyl.VectorTraits.Numerics, add some math functions (BitMath從靜態類改為抽象類. 新增名稱空間 Zyl.VectorTraits.Numerics, 增加一些的數學函數).

這次改善了標量版數學函數的組織。向量方法是基於這些標量方法的。
原來的 BitMath 類太太了。且2.0版增加了浮點類型判斷等多個函數,若仍然放在BitMath里,會使該類便的更大,不易維護。
看了一下 .NET 7.0 的泛型數學,感覺它的分類方案不錯。於是新增名稱空間 Zyl.VectorTraits.Numerics,隨後按照泛型數學的分類,建立了各個靜態類。目前有這些類。

  • BitMathCore: 本庫新增的函數。例如 BitSelect 等。
  • MathBitConverter: BitConverter(位轉換) 的數學函數。例如 SingleToInt32Bits 等。
  • MathIFloatingPoint: IFloatingPoint(浮點數介面) 的數學函數。例如 Truncate 等。
  • MathINumber: INumber(數字性介面) 的數學函數。例如 Clamp 等。
  • MathINumberBase: INumberBase(數字基本性介面) 的數學函數。例如 Abs 等。
  • MathIRootFunctions: IRootFunctions(根函數介面) 的數學函數。例如 Sqrt 等。
  • MathOperators: 運算符的數學函數。例如 BigMul 等。

目前BitMath是一個轉發彙總的作用,便於簡單的使用標量版數學函數。

基準測試程式增加命令行參數

相關日誌:

  • Benchmark programs add command line parameter (基準測試程式增加命令行參數): -accelerated0 -allowFakeBenchmark -cpuDetection0 -fixedVector0 -test0

手動運行基準測試程式時,往往希望能顯示更多的信息,便於分析數據。
而用腳本自動運行時,一般不希望顯示次要信息。
於是用命令行參數來控制比較好。

  • accelerated[=n]: 是否顯示各個向量方式的加速情況(例如 Ceiling_AcceleratedTypes 等)。
  • accelerated0: 相當於“accelerated=0”,禁止顯示各個向量方式的加速情況。
  • allowFakeBenchmark[=n]: 是否對 FakeBenchmarkAttribute 特性的函數也進行基準測試。一般情況下無需使用它,僅在腳本自動測試時,有時會用到。
  • allowFakeBenchmark0: 相當於“allowFakeBenchmark=0”,禁止FakeBenchmarkAttribute的基準測試。
  • cpuDetection[=n]: 是否顯示CPU檢測信息(例如 CpuDetectionCommand 等)。
  • cpuDetection0: 相當於“cpuDetection=0”,禁止顯示CPU檢測信息。
  • fixedVector[=n]: 是否顯示定長向量的信息(例如 Vector128/Vector256 等)。
  • fixedVector0: 相當於“fixedVector=0”,禁止顯示定長向量的信息。
  • test[=n]: 是否進行特殊測試。詳見AloneTestUtil類。
  • test0: 相當於“test=0”,禁止進行特殊測試。

增加工具程式UpdateBenchmarkResults

相關日誌:

  • Add tool program (增加工具程式): UpdateBenchmarkResults.

為了能將基準測試結果進行自動歸類與更新,開發了這一工具程式。
編譯好的程式已放在 /tools/build/ 文件夾,可以這樣使用。

  1. 在各台電腦上運行基準測試的腳本,並將結果分別放到 /articles/BenchmarkResultsRaw文件夾。
  2. 運行腳本 /tools/build/UpdateBenchmarkResults.bat。它會對評測數據進行彙總, 隨後更新到 /articles/BenchmarkResults文件夾。

該工具程式的源代碼在 /tools/UpdateBenchmarkResults 文件夾。

演算法優化

相關日誌:

  • Optimized hardware acceleration of ExtractMostSignificantBits methods in the Arm architecture (優化ExtractMostSignificantBits方法在Arm架構的硬體加速). For 8~64 bit types.

附錄

以前的發佈日誌:

作者:zyl910 出處:http://www.cnblogs.com/zyl910/ 版權聲明:自由轉載-非商用-非衍生-保持署名 | Creative Commons BY-NC-ND 3.0.
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在 CYQ.Data 版本更新的這麼多年,中間過程的版本都在完善各種功能。基於需要支持或相容的代碼越多,很多時候,常規思維,都把相關功能完成,就結束了。實現過程中,無法避免的會用到大量的反射、鎖等對性能有所影響的邏輯代碼。CYQ.Data 從V5.9 版本開始,開始大規模的優化調整代碼,目前穩定在 ... ...
  • 1.OleDb方式: 使用.NET Framework內置的System.Data.OleDb命名空間中的類,可以將Excel文件當作資料庫來讀取數據。這種方式適用於較舊版本的Excel文件(.xls格式,即Excel 2003及更早版本)。 using System.Data.OleDb; // ...
  • 一、引言 在.NET開發中,操作Office文檔(特別是Excel和Word)是一項常見的需求。然而,在伺服器端或無Microsoft Office環境的場景下,直接使用Office Interop可能會面臨挑戰。為瞭解決這個問題,開源庫NPOI應運而生,它提供了無需安裝Office即可創建、讀取和 ...
  • 一、引言 在現代應用程式開發中,尤其是在涉及I/O操作(如網路請求、文件讀寫等)時,非同步編程成為了提高性能和用戶體驗的關鍵技術。C#作為.NET框架下的主流開發語言,提供了強大的非同步編程支持,通過async/await關鍵字,可以讓開發者以同步的方式編寫非同步代碼,極大地簡化了非同步編程的複雜性。本文將 ...
  • 支持.Net/.Net Core/.Net Framework,可以部署在Docker, Windows, Linux, Mac。 常見的ORM技術(比如:Entity Framework,Dapper,SqlSugar,NHibernate,等…),它們不是在做Sql語句的程式化變種,就是在做Sq ...
  • Nuget包 Microsoft.Extensions.Telemetry.Abstractions 包含的新的日誌記錄source generator,它支持使用[LogProperties]將整個對象作為State與日誌一起記錄。 我將展示一種方法來控制如何使用[LogProperties]對象 ...
  • 概述:以上內容詳細介紹了在C#中如何從另一個線程更新GUI,包括基礎功能和高級功能。對於WinForms,使用`Control.Invoke`;對於WPF,使用`Dispatcher.Invoke`。高級功能使用`SynchronizationContext`實現線程間通信,確保清晰、可讀性高的代碼 ...
  • using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Windows.Forms; namespace OOP { pub ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...