@@ -21,16 +21,17 @@ public class SpecCpuMetricsParser : MetricsParser
2121 /// Separate the column values by 2 or more spaces.
2222 /// </summary>
2323 private static readonly Regex SpecCpuDataTableDelimiter = new Regex ( @"(\s){2,}" , RegexOptions . ExplicitCapture ) ;
24-
25- private List < Metric > metrics = new List < Metric > ( ) ;
24+ private bool isCsv ;
2625
2726 /// <summary>
2827 /// Constructor for <see cref="SpecCpuMetricsParser"/>
2928 /// </summary>
3029 /// <param name="rawText">Raw text to parse.</param>
31- public SpecCpuMetricsParser ( string rawText )
30+ /// <param name="csv">The content is from the SPEC CSV results file.</param>
31+ public SpecCpuMetricsParser ( string rawText , bool csv = false )
3232 : base ( rawText )
3333 {
34+ this . isCsv = csv ;
3435 }
3536
3637 /// <summary>
@@ -59,30 +60,29 @@ public override IList<Metric> Parse()
5960 {
6061 try
6162 {
62- this . Preprocess ( ) ;
63- this . ParseSpecCpuResult ( ) ;
64- this . ParseSpecCpuSummaryResult ( ) ;
65-
66- this . metrics . AddRange ( this . SpecCpu . GetMetrics ( nameIndex : 0 , valueIndex : 3 , unit : "Score" , namePrefix : "SPECcpu-base-" , metricRelativity : MetricRelativity . HigherIsBetter ) ) ;
67- this . metrics . AddRange ( this . SpecCpu . GetMetrics ( nameIndex : 0 , valueIndex : 7 , unit : "Score" , namePrefix : "SPECcpu-peak-" , ignoreFormatError : true , metricRelativity : MetricRelativity . HigherIsBetter ) ) ;
68- this . metrics . AddRange ( this . SpecCpuSummary . GetMetrics ( nameIndex : 0 , valueIndex : 1 , unit : "Score" , namePrefix : string . Empty , ignoreFormatError : true , metricRelativity : MetricRelativity . HigherIsBetter ) ) ;
69-
70- // Every score in SPECcpu is critical metric.
71- this . metrics . ForEach ( m => m . Verbosity = 1 ) ;
63+ IEnumerable < Metric > metrics = null ;
64+ if ( this . isCsv )
65+ {
66+ metrics = this . ParseMetricsFromCsv ( ) ;
67+ }
68+ else
69+ {
70+ metrics = this . ParseMetricsFromStandardOutput ( ) ;
71+ }
7272
73- return this . metrics ;
73+ return metrics ? . OrderBy ( m => m . Name ) . ToList ( ) ;
7474 }
7575 catch ( Exception exc )
7676 {
77- throw new WorkloadResultsException ( "Failed to parse SPECcpu metrics from results." , exc , ErrorReason . InvalidResults ) ;
77+ throw new WorkloadResultsException ( "Failed to parse SPEC CPU benchmark metrics from results." , exc , ErrorReason . InvalidResults ) ;
7878 }
7979 }
8080
8181 /// <inheritdoc/>
8282 protected override void Preprocess ( )
8383 {
8484 /*
85- * Only capture data in selected test section, which is
85+ Only capture data in selected test section, which is
8686 =================================================================================
8787 500.perlbench_r 256 757 538 * 256 694 587 *
8888 502.gcc_r 256 634 572 * 256 511 710 *
@@ -139,5 +139,226 @@ private void ParseSpecCpuSummaryResult()
139139 this . SpecCpuSummary = DataTableExtensions . ConvertToDataTable (
140140 this . Sections [ nameof ( this . SpecCpuSummary ) ] , SpecCpuMetricsParser . SpecCpuDataTableDelimiter , nameof ( this . SpecCpuSummary ) , columnNames ) ;
141141 }
142+
143+ private IEnumerable < Metric > ParseMetricsFromCsv ( )
144+ {
145+ List < Metric > metrics = new List < Metric > ( ) ;
146+
147+ /*
148+ Only capture data in selected test section, which is
149+ =================================================================================
150+ "Selected Results Table"
151+
152+ Benchmark,"Base # Copies","Est. Base Run Time","Est. Base Rate","Base Selected","Base Status","Peak # Copies","Est. Peak Run Time","Est. Peak Rate","Peak Selected","Peak Status",Description
153+ 503.bwaves_r,8,774.54528,103.575608,1,S,,,,,NR,"SelectedIteration (base #2; peak NR)"
154+ 507.cactuBSSN_r,8,529.532167,19.12632,1,S,,,,,NR,"SelectedIteration (base #1; peak NR)"
155+ 508.namd_r,8,355.876987,21.355696,1,S,,,,,NR,"SelectedIteration (base #2; peak NR)"
156+ 510.parest_r,8,855.489505,24.463184,1,S,,,,,NR,"SelectedIteration (base #1; peak NR)"
157+ 511.povray_r,8,777.63715,24.021488,1,S,,,,,NR,"SelectedIteration (base #1; peak NR)"
158+ 519.lbm_r,8,613.604624,13.741744,1,S,,,,,NR,"SelectedIteration (base #2; peak NR)"
159+ 521.wrf_r,8,575.203376,31.1542,1,S,,,,,NR,"SelectedIteration (base #1; peak NR)"
160+ 526.blender_r,8,543.972241,22.3982,1,S,,,,,NR,"SelectedIteration (base #1; peak NR)"
161+ 527.cam4_r,8,444.302751,31.49204,1,S,,,,,NR,"SelectedIteration (base #1; peak NR)"
162+ 538.imagick_r,8,731.398457,27.20268,1,S,,,,,NR,"SelectedIteration (base #1; peak NR)"
163+ 544.nab_r,8,488.412998,27.566832,1,S,,,,,NR,"SelectedIteration (base #2; peak NR)"
164+ 549.fotonik3d_r,8,940.704803,33.141112,1,S,,,,,NR,"SelectedIteration (base #1; peak NR)"
165+ 554.roms_r,8,609.94932,20.841072,1,S,,,,,NR,"SelectedIteration (base #2; peak NR)"
166+
167+ SPECrate2017_fp_base,26.914269,,26.914269
168+ SPECrate2017_fp_peak,"Not Run",,,,,,,"Not Run"
169+ */
170+
171+ Match resultsSection = Regex . Match ( this . RawText , "\" Selected Results Table\" [\\ s\\ S]+?SPEC(?:rate|speed)2017_(?:fp|int)_peak.*" , RegexOptions . IgnoreCase ) ;
172+ if ( ! resultsSection . Success )
173+ {
174+ throw new SchemaException ( $ "Invalid results. SPEC CPU benchmark outcomes/information cannot be found in the results provided.") ;
175+ }
176+
177+ IEnumerable < string > results = Regex . Split ( resultsSection . Groups [ 0 ] . Value , "[\r \n ]" ) . Where ( l => ! string . IsNullOrWhiteSpace ( l ) ) ;
178+ foreach ( string line in results )
179+ {
180+ string [ ] fields = line . Split ( ',' , StringSplitOptions . TrimEntries ) ;
181+ if ( fields . Length > 2 )
182+ {
183+ if ( fields [ 0 ] . StartsWith ( "Benchmark" ) )
184+ {
185+ continue ;
186+ }
187+
188+ if ( this . TryParseBaseMetric ( fields , out Metric baseMetric ) )
189+ {
190+ metrics . Add ( baseMetric ) ;
191+ }
192+
193+ if ( this . TryParsePeakMetric ( fields , out Metric peakMetric ) )
194+ {
195+ metrics . Add ( peakMetric ) ;
196+ }
197+
198+ if ( this . TryParseSummaryMetric ( fields , out Metric summaryMetric ) )
199+ {
200+ metrics . Add ( summaryMetric ) ;
201+ }
202+ }
203+ }
204+
205+ return metrics ;
206+ }
207+
208+ private IEnumerable < Metric > ParseMetricsFromStandardOutput ( )
209+ {
210+ List < Metric > metrics = new List < Metric > ( ) ;
211+
212+ this . Preprocess ( ) ;
213+ this . ParseSpecCpuResult ( ) ;
214+ this . ParseSpecCpuSummaryResult ( ) ;
215+
216+ metrics . AddRange ( this . SpecCpu . GetMetrics ( nameIndex : 0 , valueIndex : 3 , unit : "score" , namePrefix : "SPECcpu-base-" , metricRelativity : MetricRelativity . HigherIsBetter ) ) ;
217+ metrics . AddRange ( this . SpecCpu . GetMetrics ( nameIndex : 0 , valueIndex : 7 , unit : "score" , namePrefix : "SPECcpu-peak-" , ignoreFormatError : true , metricRelativity : MetricRelativity . HigherIsBetter ) ) ;
218+ metrics . AddRange ( this . SpecCpuSummary . GetMetrics ( nameIndex : 0 , valueIndex : 1 , unit : "score" , namePrefix : string . Empty , ignoreFormatError : true , metricRelativity : MetricRelativity . HigherIsBetter ) ) ;
219+
220+ // Every score in SPECcpu is critical metric.
221+ metrics . ForEach ( m => m . Verbosity = 0 ) ;
222+
223+ return metrics ;
224+ }
225+
226+ private bool TryParseBaseMetric ( string [ ] fields , out Metric metric )
227+ {
228+ /*
229+ "Selected Results Table"
230+
231+ Benchmark,"Base # Copies","Est. Base Run Time","Est. Base Rate","Base Selected","Base Status","Peak # Copies","Est. Peak Run Time","Est. Peak Rate","Peak Selected","Peak Status",Description
232+ 503.bwaves_r,8,774.54528,103.575608,1,S,,,,,NR,"SelectedIteration (base #2; peak NR)"
233+ 507.cactuBSSN_r,8,529.532167,19.12632,1,S,,,,,NR,"SelectedIteration (base #1; peak NR)"
234+ */
235+
236+ metric = null ;
237+
238+ // Benchmark
239+ string benchmark = fields [ 0 ] . Trim ( ) ;
240+
241+ if ( ! Regex . IsMatch ( benchmark , "^SPECrate|SPECspeed" , RegexOptions . IgnoreCase ) )
242+ {
243+ // Est. Base Rate
244+ if ( double . TryParse ( fields [ 3 ] , out double baseScore ) )
245+ {
246+ // Base # Copies
247+ double . TryParse ( fields [ 1 ] , out double baseCopies ) ;
248+
249+ // Est. Base Run Time
250+ double . TryParse ( fields [ 2 ] , out double baseRunTime ) ;
251+
252+ metric = new Metric (
253+ $ "SPECcpu-base-{ benchmark } ",
254+ baseScore ,
255+ unit : "score" ,
256+ relativity : MetricRelativity . HigherIsBetter ,
257+ description : $ "SPEC CPU '{ benchmark } ' benchmark base score.",
258+ metadata : new Dictionary < string , IConvertible >
259+ {
260+ { "benchmark" , benchmark } ,
261+ { "numCopies" , baseCopies } ,
262+ { "runTime" , baseRunTime }
263+ } ) ;
264+
265+ metric . Verbosity = 0 ;
266+ }
267+ }
268+
269+ return metric != null ;
270+ }
271+
272+ private bool TryParsePeakMetric ( string [ ] fields , out Metric metric )
273+ {
274+ /*
275+ "Selected Results Table"
276+
277+ Benchmark,"Base # Copies","Base Run Time","Base Rate","Base Selected","Base Status","Peak # Copies","Peak Run Time","Peak Rate","Peak Selected","Peak Status",Description
278+ 503.bwaves_r,128,1649.037039,778.384,1,S,128,1649.037039,778.384,1,S,"SelectedIteration (base #1; peak #1)"
279+ 507.cactuBSSN_r,128,221.93356,730.16448,1,S,128,220.578603,734.649728,1,S,"SelectedIteration (base #3; peak #3)"
280+ */
281+
282+ metric = null ;
283+
284+ // Benchmark
285+ string benchmark = fields [ 0 ] . Trim ( ) ;
286+
287+ if ( ! Regex . IsMatch ( benchmark , "^SPECrate|SPECspeed" , RegexOptions . IgnoreCase ) )
288+ {
289+ // Peak Rate
290+ if ( double . TryParse ( fields [ 8 ] , out double peakScore ) )
291+ {
292+ // Peak # Copies
293+ double . TryParse ( fields [ 6 ] , out double peakCopies ) ;
294+
295+ // Peak Run Time
296+ double . TryParse ( fields [ 7 ] , out double peakRunTime ) ;
297+
298+ metric = new Metric (
299+ $ "SPECcpu-peak-{ benchmark } ",
300+ peakScore ,
301+ unit : "score" ,
302+ relativity : MetricRelativity . HigherIsBetter ,
303+ description : $ "SPEC CPU '{ benchmark } ' benchmark peak score.",
304+ metadata : new Dictionary < string , IConvertible >
305+ {
306+ { "benchmark" , benchmark } ,
307+ { "numCopies" , peakCopies } ,
308+ { "runTime" , peakRunTime }
309+ } ) ;
310+
311+ metric . Verbosity = 0 ;
312+ }
313+ }
314+
315+ return metric != null ;
316+ }
317+
318+ private bool TryParseSummaryMetric ( string [ ] fields , out Metric metric )
319+ {
320+ /*
321+ "Selected Results Table"
322+
323+ Benchmark,"Base # Copies","Base Run Time","Base Rate","Base Selected","Base Status","Peak # Copies","Peak Run Time","Peak Rate","Peak Selected","Peak Status",Description
324+ ...
325+ ...
326+ SPECspeed2017_int_base,12.279658,,12.279658
327+ SPECspeed2017_int_peak,12.293316,,,,,,,12.293316
328+ */
329+
330+ metric = null ;
331+
332+ // Benchmark
333+ string benchmark = fields [ 0 ] . Trim ( ) ;
334+
335+ IDictionary < string , string > metricMapping = new Dictionary < string , string > ( StringComparer . OrdinalIgnoreCase )
336+ {
337+ { "SPECrate2017_fp_base" , "SPECrate(R)2017_fp_base,SPEC CPU floating point base rate summary score." } ,
338+ { "SPECrate2017_fp_peak" , "SPECrate(R)2017_fp_peak,SPEC CPU floating point peak rate summary score." } ,
339+ { "SPECrate2017_int_base" , "SPECrate(R)2017_int_base,SPEC CPU integer base rate summary score." } ,
340+ { "SPECrate2017_int_peak" , "SPECrate(R)2017_int_peak,SPEC CPU integer peak rate summary score." } ,
341+ { "SPECspeed2017_fp_base" , "SPECspeed(R)2017_fp_base,SPEC CPU floating point base speed summary score." } ,
342+ { "SPECspeed2017_fp_peak" , "SPECspeed(R)2017_fp_peak,SPEC CPU floating point peak speed summary score." } ,
343+ { "SPECspeed2017_int_base" , "SPECspeed(R)2017_int_base,SPEC CPU integer base speed summary score." } ,
344+ { "SPECspeed2017_int_peak" , "SPECspeed(R)2017_int_peak,SPEC CPU integer peak speed summary score." }
345+ } ;
346+
347+ if ( metricMapping . TryGetValue ( benchmark , out string metricDescription ) && double . TryParse ( fields [ 1 ] , out double score ) )
348+ {
349+ string [ ] metricDetails = metricDescription . Split ( ',' ) ;
350+
351+ metric = new Metric (
352+ metricDetails [ 0 ] ,
353+ score ,
354+ unit : "score" ,
355+ relativity : MetricRelativity . HigherIsBetter ,
356+ description : metricDetails [ 1 ] ) ;
357+
358+ metric . Verbosity = 0 ;
359+ }
360+
361+ return metric != null ;
362+ }
142363 }
143364}
0 commit comments