44using BenchmarkDotNet . Running ;
55using BenchmarkDotNet . Configs ;
66using BenchmarkDotNet . Reports ;
7+ using BenchmarkDotNet . Filters ;
78using System . Text ;
89using System . Runtime ;
910using System . Runtime . InteropServices ;
1213using System . Collections . Generic ;
1314using System . Linq ;
1415using BenchmarkDotNet . Columns ;
15-
16+ using System . Runtime . Intrinsics ;
17+ using System . Runtime . Intrinsics . X86 ;
18+ using System . Runtime . Intrinsics . Arm ;
19+ using System . Runtime . CompilerServices ;
1620
1721
1822namespace SimdUnicodeBenchmarks
@@ -47,6 +51,8 @@ public string GetValue(Summary summary, BenchmarkCase benchmarkCase)
4751 public UnitType UnitType { get ; } = UnitType . Dimensionless ;
4852 public string Legend { get ; } = "The speed in gigabytes per second" ;
4953 }
54+
55+
5056 [ SimpleJob ( launchCount : 1 , warmupCount : 3 , iterationCount : 3 ) ]
5157 [ Config ( typeof ( Config ) ) ]
5258 public class RealDataBenchmark
@@ -56,7 +62,44 @@ private class Config : ManualConfig
5662 {
5763 public Config ( )
5864 {
59- AddColumn ( new Speed ( ) ) ;
65+ AddColumn ( new Speed ( ) ) ;
66+
67+
68+ if ( RuntimeInformation . ProcessArchitecture == Architecture . Arm64 )
69+ {
70+ Console . WriteLine ( "ARM64 system detected." ) ;
71+ AddFilter ( new AnyCategoriesFilter ( [ "arm64" , "scalar" , "runtime" ] ) ) ;
72+
73+ }
74+ else if ( RuntimeInformation . ProcessArchitecture == Architecture . X64 )
75+ {
76+ if ( Vector512 . IsHardwareAccelerated && System . Runtime . Intrinsics . X86 . Avx512Vbmi . IsSupported )
77+ {
78+ Console . WriteLine ( "X64 system detected (Intel, AMD,...) with AVX-512 support." ) ;
79+ AddFilter ( new AnyCategoriesFilter ( [ "avx512" , "avx" , "sse" , "scalar" , "runtime" ] ) ) ;
80+ }
81+ else if ( Avx2 . IsSupported )
82+ {
83+ Console . WriteLine ( "X64 system detected (Intel, AMD,...) with AVX2 support." ) ;
84+ AddFilter ( new AnyCategoriesFilter ( [ "avx" , "sse" , "scalar" , "runtime" ] ) ) ;
85+ }
86+ else if ( Sse42 . IsSupported )
87+ {
88+ Console . WriteLine ( "X64 system detected (Intel, AMD,...) with Sse4.2 support." ) ;
89+ AddFilter ( new AnyCategoriesFilter ( [ "sse" , "scalar" , "runtime" ] ) ) ;
90+ }
91+ else
92+ {
93+ Console . WriteLine ( "X64 system detected (Intel, AMD,...) without relevant SIMD support." ) ;
94+ AddFilter ( new AnyCategoriesFilter ( [ "scalar" , "runtime" ] ) ) ;
95+ }
96+ }
97+ else
98+ {
99+ AddFilter ( new AnyCategoriesFilter ( [ "scalar" , "runtime" ] ) ) ;
100+
101+ }
102+
60103 }
61104 }
62105 // Parameters and variables for real data
@@ -128,42 +171,83 @@ public void Setup()
128171 }
129172
130173 [ Benchmark ]
174+ [ BenchmarkCategory ( "default" , "runtime" ) ]
131175 public unsafe void DotnetRuntimeUtf8ValidationRealData ( )
132176 {
133177 RunDotnetRuntimeUtf8ValidationBenchmark ( allLinesUtf8 , DotnetRuntime . Utf8Utility . GetPointerToFirstInvalidByte ) ;
134178 }
135179
136180 [ Benchmark ]
181+ [ BenchmarkCategory ( "default" ) ]
137182 public unsafe void SIMDUtf8ValidationRealData ( )
138183 {
139184 if ( allLinesUtf8 != null )
140185 {
141186 RunUtf8ValidationBenchmark ( allLinesUtf8 , SimdUnicode . UTF8 . GetPointerToFirstInvalidByte ) ;
142187 }
143188 }
144- }
145189
146- public class Program
147- {
148- // TODO: adopt BenchmarkSwitcher https://benchmarkdotnet.org/articles/guides/how-to-run.html
149- public static void Main ( string [ ] args )
190+ [ Benchmark ]
191+ [ BenchmarkCategory ( "scalar" ) ]
192+ public unsafe void Utf8ValidationRealDataScalar ( )
193+ {
194+ if ( allLinesUtf8 != null )
195+ {
196+ RunUtf8ValidationBenchmark ( allLinesUtf8 , SimdUnicode . UTF8 . GetPointerToFirstInvalidByteScalar ) ;
197+ }
198+ }
199+ [ Benchmark ]
200+ [ BenchmarkCategory ( "arm64" ) ]
201+ public unsafe void SIMDUtf8ValidationRealDataArm64 ( )
202+ {
203+ if ( allLinesUtf8 != null )
204+ {
205+ RunUtf8ValidationBenchmark ( allLinesUtf8 , SimdUnicode . UTF8 . GetPointerToFirstInvalidByteArm64 ) ;
206+ }
207+ }
208+ [ Benchmark ]
209+ [ BenchmarkCategory ( "avx" ) ]
210+ public unsafe void SIMDUtf8ValidationRealDataAvx2 ( )
150211 {
151- if ( RuntimeInformation . ProcessArchitecture == Architecture . Arm64 )
212+ if ( allLinesUtf8 != null )
152213 {
153- Console . WriteLine ( "ARM64 system detected." ) ;
214+ RunUtf8ValidationBenchmark ( allLinesUtf8 , SimdUnicode . UTF8 . GetPointerToFirstInvalidByteAvx2 ) ;
154215 }
155- else if ( RuntimeInformation . ProcessArchitecture == Architecture . X64 )
216+ }
217+ /*
218+ // TODO: enable this benchmark when the SSE implementation is ready
219+ [Benchmark]
220+ [BenchmarkCategory("sse")]
221+ public unsafe void SIMDUtf8ValidationRealDataSse()
222+ {
223+ if (allLinesUtf8 != null)
156224 {
157- Console . WriteLine ( "X64 system detected (Intel, AMD,...)." ) ;
225+ RunUtf8ValidationBenchmark(allLinesUtf8, SimdUnicode.UTF8.GetPointerToFirstInvalidByteSse );
158226 }
159- else
227+ }*/
228+ /*
229+ // TODO: enable this benchmark when the AVX-512 implementation is ready
230+ [Benchmark]
231+ [BenchmarkCategory("avx512")]
232+ public unsafe void SIMDUtf8ValidationRealDataAvx512()
233+ {
234+ if (allLinesUtf8 != null)
160235 {
161- Console . WriteLine ( "Unrecognized system." ) ;
236+ RunUtf8ValidationBenchmark(allLinesUtf8, SimdUnicode.UTF8.GetPointerToFirstInvalidByteAvx512 );
162237 }
238+ }*/
163239
240+ }
241+ public class Program
242+ {
243+ // TODO: adopt BenchmarkSwitcher https://benchmarkdotnet.org/articles/guides/how-to-run.html
244+ /*public static void Main(string[] args)
245+ {
164246 var config = DefaultConfig.Instance.WithSummaryStyle(SummaryStyle.Default.WithMaxParameterColumnWidth(100));
165247 BenchmarkRunner.Run<RealDataBenchmark>(config);
166- }
248+ }*/
249+ static void Main ( string [ ] args ) => BenchmarkSwitcher . FromAssembly ( typeof ( Program ) . Assembly ) . Run ( args ) ;
250+
167251
168252 }
169253
0 commit comments