param( [Parameter(Mandatory = $true)] [string]$InputDirectory ) $ErrorActionPreference = 'Stop' $invariant = [Globalization.CultureInfo]::InvariantCulture [Threading.Thread]::CurrentThread.CurrentCulture = $invariant [Threading.Thread]::CurrentThread.CurrentUICulture = $invariant function ConvertTo-Number($Value) { if ($Value -is [double] -or $Value -is [float] -or $Value -is [decimal]) { return [double]$Value } $text = ([string]$Value).Trim() if ($text.Contains(',') -and -not $text.Contains('.')) { $text = $text.Replace(',', '.') } return [double]::Parse($text, [Globalization.NumberStyles]::Float, $invariant) } $directory = if ([IO.Path]::IsPathRooted($InputDirectory)) { [IO.Path]::GetFullPath($InputDirectory) } else { [IO.Path]::GetFullPath((Join-Path (Resolve-Path '.').Path $InputDirectory)) } $input = Join-Path $directory 'cell-medians-large.csv' if (-not (Test-Path -LiteralPath $input -PathType Leaf)) { throw "Missing cell medians: $input" } function Get-GeometricMean($Values) { $positive = @($Values | Where-Object { (ConvertTo-Number $_) -gt 0 }) if ($positive.Count -eq 0) { return [double]::NaN } $meanLog = ($positive | ForEach-Object { [math]::Log((ConvertTo-Number $_)) } | Measure-Object -Average).Average return [math]::Exp($meanLog) } $medians = @(Import-Csv -LiteralPath $input) $comparisons = @($medians | Group-Object profile,type,workload,n | ForEach-Object { $rows = @($_.Group) $fixed = @($rows | Where-Object { $_.structure -like 'tiered_forced_leaf_*' } | Sort-Object { ConvertTo-Number $_.median_ns_per_op }) $adaptive = @($rows | Where-Object { $_.structure -like 'adaptive_shape_deferred*' })[0] $vector = @($rows | Where-Object { $_.structure -eq 'std::vector_reserved' })[0] if ($fixed.Count -ne 5 -or $null -eq $adaptive -or $null -eq $vector) { throw "Incomplete seven-candidate cell: $($_.Name)" } $best = $fixed[0] $ppmMatch = [regex]::Match($adaptive.workload, '_edit_ppm_(\d+)$') if (-not $ppmMatch.Success) { throw "Invalid large workload: $($adaptive.workload)" } $editPpm = [int]$ppmMatch.Groups[1].Value $pattern = $adaptive.workload.Substring( 0, $adaptive.workload.Length - $ppmMatch.Value.Length) $bestLeaf = [regex]::Match($best.structure, 'leaf_(\d+)').Groups[1].Value $fixedNs = ConvertTo-Number $best.median_ns_per_op $adaptiveNs = ConvertTo-Number $adaptive.median_ns_per_op $vectorNs = ConvertTo-Number $vector.median_ns_per_op [pscustomobject]@{ profile = $adaptive.profile type = $adaptive.type n = [long]$adaptive.n pattern = $pattern edit_ppm = $editPpm workload = $adaptive.workload best_fixed_leaf = [int]$bestLeaf best_fixed_ns_per_op = $fixedNs adaptive_ns_per_op = $adaptiveNs vector_ns_per_op = $vectorNs adaptive_over_best_fixed = $adaptiveNs / $fixedNs vector_over_best_fixed = $vectorNs / $fixedNs adaptive_over_vector = $adaptiveNs / $vectorNs adaptive_switches = ConvertTo-Number $adaptive.median_switches adaptive_leaf_rebuilds = ConvertTo-Number $adaptive.median_leaf_rebuilds adaptive_final_mode = $adaptive.final_mode adaptive_final_leaf = [int]$adaptive.final_leaf adaptive_transition_ns = ConvertTo-Number $adaptive.median_max_transition_ns adaptive_construction_ns = ConvertTo-Number $adaptive.median_construction_ns vector_construction_ns = ConvertTo-Number $vector.median_construction_ns best_fixed_construction_ns = ConvertTo-Number $best.median_construction_ns } }) $comparisons | Sort-Object n,pattern,edit_ppm,profile | Export-Csv -LiteralPath (Join-Path $directory 'comparison-large.csv') ` -NoTypeInformation -Encoding utf8 $bySize = @($comparisons | Group-Object n | ForEach-Object { $cells = @($_.Group) [pscustomobject]@{ n = [long]$cells[0].n cells = $cells.Count gm_adaptive_over_best_fixed = Get-GeometricMean $cells.adaptive_over_best_fixed gm_vector_over_best_fixed = Get-GeometricMean $cells.vector_over_best_fixed gm_adaptive_over_vector = Get-GeometricMean $cells.adaptive_over_vector adaptive_beats_best_fixed = @($cells | Where-Object { $_.adaptive_over_best_fixed -lt 1 }).Count adaptive_beats_vector = @($cells | Where-Object { $_.adaptive_over_vector -lt 1 }).Count adaptive_final_vector = @($cells | Where-Object { $_.adaptive_final_mode -eq 'vector' }).Count adaptive_final_tiered = @($cells | Where-Object { $_.adaptive_final_mode -eq 'tiered' }).Count } }) $bySize | Sort-Object n | Export-Csv ` -LiteralPath (Join-Path $directory 'comparison-by-size.csv') ` -NoTypeInformation -Encoding utf8 $byWorkload = @($comparisons | Group-Object n,pattern,edit_ppm | ForEach-Object { $cells = @($_.Group) [pscustomobject]@{ n = [long]$cells[0].n pattern = $cells[0].pattern edit_ppm = [int]$cells[0].edit_ppm profiles = $cells.Count best_fixed_leaf_mode = ($cells | Group-Object best_fixed_leaf | Sort-Object Count -Descending | Select-Object -First 1).Name gm_adaptive_over_best_fixed = Get-GeometricMean $cells.adaptive_over_best_fixed gm_vector_over_best_fixed = Get-GeometricMean $cells.vector_over_best_fixed gm_adaptive_over_vector = Get-GeometricMean $cells.adaptive_over_vector mean_switches = ($cells.adaptive_switches | Measure-Object -Average).Average mean_leaf_rebuilds = ($cells.adaptive_leaf_rebuilds | Measure-Object -Average).Average final_modes = (($cells.adaptive_final_mode | Group-Object | ForEach-Object { "$($_.Name):$($_.Count)" }) -join ';') } }) $byWorkload | Sort-Object n,pattern,edit_ppm | Export-Csv ` -LiteralPath (Join-Path $directory 'comparison-by-workload.csv') ` -NoTypeInformation -Encoding utf8 $winners = @($comparisons | Group-Object best_fixed_leaf | ForEach-Object { [pscustomobject]@{ leaf = [int]$_.Name wins = $_.Count percent = 100.0 * $_.Count / $comparisons.Count } }) $winners | Sort-Object wins -Descending | Export-Csv ` -LiteralPath (Join-Path $directory 'fixed-leaf-winners.csv') ` -NoTypeInformation -Encoding utf8 Write-Host "Large comparison analysis: $directory" $bySize | Sort-Object n | Format-Table -AutoSize $winners | Sort-Object wins -Descending | Format-Table -AutoSize