Add Avx512 support to IndexOfAnyAsciiSearcher - #103710

Merged
MihaZupan merged 1 commit into
dotnet:mainfrom
MihaZupan:searchvalues-ascii-avx512-5
Jun 22, 2024
Merged

Add Avx512 support to IndexOfAnyAsciiSearcher#103710
MihaZupan merged 1 commit into
dotnet:mainfrom
MihaZupan:searchvalues-ascii-avx512-5

Conversation

@MihaZupan

Copy link
Copy Markdown
Member

Closes#93222

Pretty much a copy-paste of the existing Vector128/Vector256 paths (#93222 (comment)).
I had to spam a couple more AggressiveInlinings to get all the small helpers to inline even in microbenchmarks where they're never called. This is the source of slight improvements for early matches in a couple benchmarks below.

Numbers-wise it's a ~0.5 - 1 ns regression for early matches, and a speedup to ~1.5x in throughput for longer inputs.

Early matches
MethodToolchainLengthMatchAtStartMeanErrorRatio
IndexOfAny_Charmain32True4.885 ns0.0129 ns1.00
IndexOfAny_Charpr32True3.343 ns0.0007 ns0.68
IndexOfAnyExcept_Charmain32True3.056 ns0.0008 ns1.00
IndexOfAnyExcept_Charpr32True3.152 ns0.0095 ns1.03
LastIndexOfAny_Charmain32True4.166 ns0.0522 ns1.00
LastIndexOfAny_Charpr32True3.564 ns0.0748 ns0.86
LastIndexOfAnyExcept_Charmain32True3.550 ns0.0008 ns1.00
LastIndexOfAnyExcept_Charpr32True3.561 ns0.0007 ns1.00
IndexOfAny_Charmain33True3.463 ns0.0023 ns1.00
IndexOfAny_Charpr33True3.598 ns0.0037 ns1.04
IndexOfAnyExcept_Charmain33True2.834 ns0.0106 ns1.00
IndexOfAnyExcept_Charpr33True3.660 ns0.0064 ns1.29
LastIndexOfAny_Charmain33True4.158 ns0.0082 ns1.00
LastIndexOfAny_Charpr33True3.951 ns0.0004 ns0.95
LastIndexOfAnyExcept_Charmain33True3.162 ns0.0053 ns1.00
LastIndexOfAnyExcept_Charpr33True4.114 ns0.0006 ns1.30
IndexOfAny_Charmain65True3.464 ns0.0028 ns1.00
IndexOfAny_Charpr65True3.504 ns0.0768 ns1.01
IndexOfAnyExcept_Charmain65True2.833 ns0.0137 ns1.00
IndexOfAnyExcept_Charpr65True3.581 ns0.1278 ns1.26
LastIndexOfAny_Charmain65True4.128 ns0.0257 ns1.00
LastIndexOfAny_Charpr65True3.402 ns0.0005 ns0.82
LastIndexOfAnyExcept_Charmain65True3.030 ns0.0152 ns1.00
LastIndexOfAnyExcept_Charpr65True3.457 ns0.0019 ns1.14
IndexOfAny_Charmain10000True3.466 ns0.0035 ns1.00
IndexOfAny_Charpr10000True3.397 ns0.0004 ns0.98
IndexOfAnyExcept_Charmain10000True2.822 ns0.0111 ns1.00
IndexOfAnyExcept_Charpr10000True3.402 ns0.0012 ns1.20
LastIndexOfAny_Charmain10000True3.846 ns0.0118 ns1.00
LastIndexOfAny_Charpr10000True3.806 ns0.0153 ns0.99
LastIndexOfAnyExcept_Charmain10000True3.030 ns0.0044 ns1.00
LastIndexOfAnyExcept_Charpr10000True3.467 ns0.0014 ns1.14
Throughput
MethodToolchainLengthMatchAtStartMeanErrorRatio
IndexOfAny_Charmain32False3.109 ns0.0027 ns1.00
IndexOfAny_Charpr32False2.625 ns0.0006 ns0.84
IndexOfAnyExcept_Charmain32False2.460 ns0.0025 ns1.00
IndexOfAnyExcept_Charpr32False3.084 ns0.0783 ns1.25
LastIndexOfAny_Charmain32False3.063 ns0.0087 ns1.00
LastIndexOfAny_Charpr32False2.865 ns0.1573 ns0.94
LastIndexOfAnyExcept_Charmain32False3.646 ns0.4223 ns1.00
LastIndexOfAnyExcept_Charpr32False2.426 ns0.0036 ns0.68
IndexOfAny_Charmain33False4.343 ns0.0232 ns1.00
IndexOfAny_Charpr33False3.146 ns0.0026 ns0.72
IndexOfAnyExcept_Charmain33False4.320 ns0.2929 ns1.00
IndexOfAnyExcept_Charpr33False3.038 ns0.0004 ns0.71
LastIndexOfAny_Charmain33False4.913 ns0.0303 ns1.00
LastIndexOfAny_Charpr33False3.017 ns0.0008 ns0.61
LastIndexOfAnyExcept_Charmain33False3.896 ns0.0007 ns1.00
LastIndexOfAnyExcept_Charpr33False3.440 ns0.0003 ns0.88
IndexOfAny_Charmain65False5.708 ns0.0108 ns1.00
IndexOfAny_Charpr65False4.236 ns0.0008 ns0.74
IndexOfAnyExcept_Charmain65False5.004 ns0.0600 ns1.00
IndexOfAnyExcept_Charpr65False4.259 ns0.0068 ns0.85
LastIndexOfAny_Charmain65False6.250 ns0.1711 ns1.00
LastIndexOfAny_Charpr65False4.242 ns0.0043 ns0.68
LastIndexOfAnyExcept_Charmain65False6.590 ns0.7326 ns1.00
LastIndexOfAnyExcept_Charpr65False4.174 ns0.0598 ns0.65
IndexOfAny_Charmain10000False331.894 ns0.2110 ns1.00
IndexOfAny_Charpr10000False208.743 ns0.0179 ns0.63
IndexOfAnyExcept_Charmain10000False375.454 ns0.0229 ns1.00
IndexOfAnyExcept_Charpr10000False260.705 ns0.0650 ns0.69
LastIndexOfAny_Charmain10000False333.720 ns0.0841 ns1.00
LastIndexOfAny_Charpr10000False209.806 ns0.0891 ns0.63
LastIndexOfAnyExcept_Charmain10000False378.696 ns0.3796 ns1.00
LastIndexOfAnyExcept_Charpr10000False262.419 ns0.4015 ns0.69

I'll rerun the Regex benchmarks.

@MihaZupan

Copy link
Copy Markdown
MemberAuthor

@MihuBot benchmark Regex

@MihuBot

MihuBot commented Jun 20, 2024

Copy link
Copy Markdown
System.Text.RegularExpressions.Tests.Perf_Regex_Industry_RustLang_Sherlock
BenchmarkDotNet v0.13.13-nightly.20240311.145, Ubuntu 22.04.4 LTS (Jammy Jellyfish)
Intel Xeon Platinum 8370C CPU 2.80GHz, 1 CPU, 8 logical and 4 physical cores
MediumRun : .NET 9.0.0 (42.42.42.42424), X64 RyuJIT AVX-512F+CD+BW+DQ+VL+VBMI
Job=MediumRun OutlierMode=DontRemove IterationCount=15
LaunchCount=2 MemoryRandomization=True WarmupCount=10
MethodToolchainPatternMeanErrorRatioAllocatedAlloc Ratio
CountMain.*691,131.27 ns842.077 ns1.002 B1.00
CountPR.*701,291.96 ns4,208.201 ns1.012 B1.00
CountMain(?i)Holmes71,847.44 ns471.748 ns1.00-NA
CountPR(?i)Holmes72,181.78 ns346.591 ns1.00-NA
CountMain(?i)Sher[a-z]+|Hol[a-z]+102,412.23 ns2,482.554 ns1.00-NA
CountPR(?i)Sher[a-z]+|Hol[a-z]+100,226.97 ns4,693.052 ns0.98-NA
CountMain(?i)Sherlock63,157.23 ns286.797 ns1.00-NA
CountPR(?i)Sherlock63,592.22 ns294.601 ns1.013 BNA
CountMain(?i)Sherlock Holmes63,163.87 ns353.487 ns1.00-NA
CountPR(?i)Sherlock Holmes63,130.32 ns312.279 ns1.00-NA
CountMain(?i)Sherlock|Holmes|Watson96,989.85 ns3,823.367 ns1.00-NA
CountPR(?i)Sherlock|Holmes|Watson96,919.46 ns4,402.650 ns1.00-NA
CountMain(?i)Sherlock|(...)er|John|Baker [49]292,458.32 ns4,255.586 ns1.002 B1.00
CountPR(?i)Sherlock|(...)er|John|Baker [49]291,038.70 ns5,906.277 ns1.002 B1.00
CountMain(?i)the380,816.71 ns448.532 ns1.001 B1.00
CountPR(?i)the378,387.61 ns597.080 ns0.991 B1.00
CountMain(?m)^Sherlock(...)rlock Holmes$ [37]80,760.72 ns4,306.860 ns1.01-NA
CountPR(?m)^Sherlock(...)rlock Holmes$ [37]82,582.68 ns3,929.177 ns1.03-NA
CountMain(?s).*51.49 ns0.230 ns1.00-NA
CountPR(?s).*51.44 ns0.201 ns1.00-NA
CountMain[^\\n]*696,503.75 ns1,189.220 ns1.002 B1.00
CountPR[^\\n]*701,777.91 ns4,947.894 ns1.012 B1.00
CountMain[a-q][^u-z]{13}x34,252.94 ns271.978 ns1.00-NA
CountPR[a-q][^u-z]{13}x32,601.06 ns1,062.765 ns0.95-NA
CountMain[a-zA-Z]+ing4,743,957.65 ns35,002.412 ns1.0021 B1.00
CountPR[a-zA-Z]+ing4,892,478.29 ns15,606.673 ns1.0321 B1.00
CountMain\b\w+n\b9,984,392.53 ns16,833.207 ns1.0044 B1.00
CountPR\b\w+n\b10,828,533.01 ns36,736.622 ns1.0839 B0.89
CountMain\p{L}10,603,931.90 ns48,819.499 ns1.0035 B1.00
CountPR\p{L}11,179,680.36 ns9,486.172 ns1.0531 B0.89
CountMain\p{Ll}10,195,145.76 ns27,272.582 ns1.0035 B1.00
CountPR\p{Ll}11,436,304.68 ns77,659.485 ns1.1235 B1.00
CountMain\p{Lu}512,487.85 ns3,951.166 ns1.002 B1.00
CountPR\p{Lu}465,932.29 ns13,751.745 ns0.911 B0.50
CountMain\s[a-zA-Z]{0,12}ing\s5,401,364.31 ns12,575.532 ns1.0024 B1.00
CountPR\s[a-zA-Z]{0,12}ing\s5,785,507.55 ns101,020.912 ns1.0724 B1.00
CountMain\w+5,177,572.11 ns28,630.119 ns1.0018 B1.00
CountPR\w+5,505,569.07 ns66,941.247 ns1.0618 B1.00
CountMain\w+\s+Holmes4,021,934.73 ns23,376.720 ns1.0022 B1.00
CountPR\w+\s+Holmes4,287,127.11 ns34,628.196 ns1.0722 B1.00
CountMain\w+\s+Holmes\s+\w+4,157,736.06 ns3,369.514 ns1.0023 B1.00
CountPR\w+\s+Holmes\s+\w+4,448,197.47 ns8,704.825 ns1.0723 B1.00
CountMainaei60,226.44 ns177.769 ns1.00-NA
CountPRaei59,984.97 ns231.105 ns1.00-NA
CountMainaqj60,359.02 ns219.068 ns1.00-NA
CountPRaqj60,216.79 ns250.061 ns1.00-NA
CountMainHolmes70,247.90 ns381.235 ns1.00-NA
CountPRHolmes70,191.66 ns312.375 ns1.00-NA
CountMainHolmes.{0,25}(...).{0,25}Holmes [39]59,812.45 ns223.860 ns1.00-NA
CountPRHolmes.{0,25}(...).{0,25}Holmes [39]61,210.71 ns1,547.310 ns1.02-NA
CountMainSher[a-z]+|Hol[a-z]+66,397.69 ns761.073 ns1.00-NA
CountPRSher[a-z]+|Hol[a-z]+64,849.71 ns1,154.795 ns0.983 BNA
CountMainSherlock85,985.04 ns1,966.243 ns1.00-NA
CountPRSherlock83,371.97 ns3,793.039 ns0.97-NA
CountMainSherlock Holmes82,774.02 ns3,862.238 ns1.01-NA
CountPRSherlock Holmes85,172.83 ns2,128.470 ns1.03-NA
CountMainSherlock\s+Holmes83,442.70 ns3,644.738 ns1.00-NA
CountPRSherlock\s+Holmes81,539.97 ns4,064.719 ns0.98-NA
CountMainSherlock|Holmes57,513.25 ns1,431.014 ns1.00-NA
CountPRSherlock|Holmes58,628.39 ns909.981 ns1.02-NA
CountMainSherlock|Holmes|Watson81,797.43 ns3,871.627 ns1.00-NA
CountPRSherlock|Holmes|Watson77,711.13 ns263.733 ns0.95-NA
CountMainSherlock|Holm(...)er|John|Baker [45]204,100.20 ns4,644.087 ns1.001 B1.00
CountPRSherlock|Holm(...)er|John|Baker [45]209,457.96 ns1,109.672 ns1.031 B1.00
CountMainSherlock|Street34,583.11 ns1,498.786 ns1.00-NA
CountPRSherlock|Street37,804.48 ns905.387 ns1.10-NA
CountMainthe308,111.60 ns2,660.420 ns1.001 B1.00
CountPRthe304,342.71 ns867.519 ns0.991 B1.00
CountMainThe74,898.95 ns553.273 ns1.00-NA
CountPRThe74,592.77 ns544.687 ns1.00-NA
CountMainthe\s+\w+448,325.25 ns1,314.530 ns1.001 B1.00
CountPRthe\s+\w+457,653.52 ns8,459.813 ns1.021 B1.00
CountMainzqj59,408.54 ns583.905 ns1.00-NA
CountPRzqj59,892.80 ns549.900 ns1.01-NA

A few other runs

public BitVector256 Lookup = lookup;

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly Vector128<byte> Bitmap128() => Bitmap512._lower._lower;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: why a method rather than a property?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a bit more code to define the get since we need the MethodImpl on it. No other reason.

public struct AsciiState(Vector128<byte> bitmap, BitVector256 lookup)
{
public Vector256<byte> Bitmap = Vector256.Create(bitmap);
public Vector512<byte> Bitmap512 = Vector512.Create(bitmap);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These can't / shouldn't be readonly?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The TryIndexOfAny helpers (called by non-searchvalues IndexOfAny) are writing into this field directly when computing the bitmap to avoid needing an extra local.
As far as the vectorized code is concerned, these could be readonly.

@MihaZupan
MihaZupan merged commit ce1ae77 into dotnet:mainJun 22, 2024
rzikm pushed a commit to rzikm/dotnet-runtime that referenced this pull request Jun 24, 2024
MihaZupan added a commit to MihaZupan/runtime that referenced this pull request Jul 10, 2024
MihaZupan added a commit that referenced this pull request Jul 10, 2024
…4688)
* Revert "Add Avx512 support to IndexOfAnyAsciiSearcher (#103710)"
This reverts commit ce1ae77.
* Keep the test improvements
* Keep the inlining changes
* Keep the shift improvements
matouskozak added a commit to matouskozak/runtime that referenced this pull request Jul 11, 2024
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jul 23, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Light up IndexOfAnyAsciiSearcher for AVX512

3 participants

@MihaZupan@MihuBot@stephentoub
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Add Avx512 support to IndexOfAnyAsciiSearcher - #103710

Merged
MihaZupan merged 1 commit into
dotnet:mainfrom
MihaZupan:searchvalues-ascii-avx512-5
Jun 22, 2024
Merged

Add Avx512 support to IndexOfAnyAsciiSearcher#103710
MihaZupan merged 1 commit into
dotnet:mainfrom
MihaZupan:searchvalues-ascii-avx512-5

Conversation

@MihaZupan

Copy link
Copy Markdown
Member

Closes#93222

Pretty much a copy-paste of the existing Vector128/Vector256 paths (#93222 (comment)).
I had to spam a couple more AggressiveInlinings to get all the small helpers to inline even in microbenchmarks where they're never called. This is the source of slight improvements for early matches in a couple benchmarks below.

Numbers-wise it's a ~0.5 - 1 ns regression for early matches, and a speedup to ~1.5x in throughput for longer inputs.

Early matches
MethodToolchainLengthMatchAtStartMeanErrorRatio
IndexOfAny_Charmain32True4.885 ns0.0129 ns1.00
IndexOfAny_Charpr32True3.343 ns0.0007 ns0.68
IndexOfAnyExcept_Charmain32True3.056 ns0.0008 ns1.00
IndexOfAnyExcept_Charpr32True3.152 ns0.0095 ns1.03
LastIndexOfAny_Charmain32True4.166 ns0.0522 ns1.00
LastIndexOfAny_Charpr32True3.564 ns0.0748 ns0.86
LastIndexOfAnyExcept_Charmain32True3.550 ns0.0008 ns1.00
LastIndexOfAnyExcept_Charpr32True3.561 ns0.0007 ns1.00
IndexOfAny_Charmain33True3.463 ns0.0023 ns1.00
IndexOfAny_Charpr33True3.598 ns0.0037 ns1.04
IndexOfAnyExcept_Charmain33True2.834 ns0.0106 ns1.00
IndexOfAnyExcept_Charpr33True3.660 ns0.0064 ns1.29
LastIndexOfAny_Charmain33True4.158 ns0.0082 ns1.00
LastIndexOfAny_Charpr33True3.951 ns0.0004 ns0.95
LastIndexOfAnyExcept_Charmain33True3.162 ns0.0053 ns1.00
LastIndexOfAnyExcept_Charpr33True4.114 ns0.0006 ns1.30
IndexOfAny_Charmain65True3.464 ns0.0028 ns1.00
IndexOfAny_Charpr65True3.504 ns0.0768 ns1.01
IndexOfAnyExcept_Charmain65True2.833 ns0.0137 ns1.00
IndexOfAnyExcept_Charpr65True3.581 ns0.1278 ns1.26
LastIndexOfAny_Charmain65True4.128 ns0.0257 ns1.00
LastIndexOfAny_Charpr65True3.402 ns0.0005 ns0.82
LastIndexOfAnyExcept_Charmain65True3.030 ns0.0152 ns1.00
LastIndexOfAnyExcept_Charpr65True3.457 ns0.0019 ns1.14
IndexOfAny_Charmain10000True3.466 ns0.0035 ns1.00
IndexOfAny_Charpr10000True3.397 ns0.0004 ns0.98
IndexOfAnyExcept_Charmain10000True2.822 ns0.0111 ns1.00
IndexOfAnyExcept_Charpr10000True3.402 ns0.0012 ns1.20
LastIndexOfAny_Charmain10000True3.846 ns0.0118 ns1.00
LastIndexOfAny_Charpr10000True3.806 ns0.0153 ns0.99
LastIndexOfAnyExcept_Charmain10000True3.030 ns0.0044 ns1.00
LastIndexOfAnyExcept_Charpr10000True3.467 ns0.0014 ns1.14
Throughput
MethodToolchainLengthMatchAtStartMeanErrorRatio
IndexOfAny_Charmain32False3.109 ns0.0027 ns1.00
IndexOfAny_Charpr32False2.625 ns0.0006 ns0.84
IndexOfAnyExcept_Charmain32False2.460 ns0.0025 ns1.00
IndexOfAnyExcept_Charpr32False3.084 ns0.0783 ns1.25
LastIndexOfAny_Charmain32False3.063 ns0.0087 ns1.00
LastIndexOfAny_Charpr32False2.865 ns0.1573 ns0.94
LastIndexOfAnyExcept_Charmain32False3.646 ns0.4223 ns1.00
LastIndexOfAnyExcept_Charpr32False2.426 ns0.0036 ns0.68
IndexOfAny_Charmain33False4.343 ns0.0232 ns1.00
IndexOfAny_Charpr33False3.146 ns0.0026 ns0.72
IndexOfAnyExcept_Charmain33False4.320 ns0.2929 ns1.00
IndexOfAnyExcept_Charpr33False3.038 ns0.0004 ns0.71
LastIndexOfAny_Charmain33False4.913 ns0.0303 ns1.00
LastIndexOfAny_Charpr33False3.017 ns0.0008 ns0.61
LastIndexOfAnyExcept_Charmain33False3.896 ns0.0007 ns1.00
LastIndexOfAnyExcept_Charpr33False3.440 ns0.0003 ns0.88
IndexOfAny_Charmain65False5.708 ns0.0108 ns1.00
IndexOfAny_Charpr65False4.236 ns0.0008 ns0.74
IndexOfAnyExcept_Charmain65False5.004 ns0.0600 ns1.00
IndexOfAnyExcept_Charpr65False4.259 ns0.0068 ns0.85
LastIndexOfAny_Charmain65False6.250 ns0.1711 ns1.00
LastIndexOfAny_Charpr65False4.242 ns0.0043 ns0.68
LastIndexOfAnyExcept_Charmain65False6.590 ns0.7326 ns1.00
LastIndexOfAnyExcept_Charpr65False4.174 ns0.0598 ns0.65
IndexOfAny_Charmain10000False331.894 ns0.2110 ns1.00
IndexOfAny_Charpr10000False208.743 ns0.0179 ns0.63
IndexOfAnyExcept_Charmain10000False375.454 ns0.0229 ns1.00
IndexOfAnyExcept_Charpr10000False260.705 ns0.0650 ns0.69
LastIndexOfAny_Charmain10000False333.720 ns0.0841 ns1.00
LastIndexOfAny_Charpr10000False209.806 ns0.0891 ns0.63
LastIndexOfAnyExcept_Charmain10000False378.696 ns0.3796 ns1.00
LastIndexOfAnyExcept_Charpr10000False262.419 ns0.4015 ns0.69

I'll rerun the Regex benchmarks.

@MihaZupan

Copy link
Copy Markdown
MemberAuthor

@MihuBot benchmark Regex

@MihuBot

MihuBot commented Jun 20, 2024

Copy link
Copy Markdown
System.Text.RegularExpressions.Tests.Perf_Regex_Industry_RustLang_Sherlock
BenchmarkDotNet v0.13.13-nightly.20240311.145, Ubuntu 22.04.4 LTS (Jammy Jellyfish)
Intel Xeon Platinum 8370C CPU 2.80GHz, 1 CPU, 8 logical and 4 physical cores
MediumRun : .NET 9.0.0 (42.42.42.42424), X64 RyuJIT AVX-512F+CD+BW+DQ+VL+VBMI
Job=MediumRun OutlierMode=DontRemove IterationCount=15
LaunchCount=2 MemoryRandomization=True WarmupCount=10
MethodToolchainPatternMeanErrorRatioAllocatedAlloc Ratio
CountMain.*691,131.27 ns842.077 ns1.002 B1.00
CountPR.*701,291.96 ns4,208.201 ns1.012 B1.00
CountMain(?i)Holmes71,847.44 ns471.748 ns1.00-NA
CountPR(?i)Holmes72,181.78 ns346.591 ns1.00-NA
CountMain(?i)Sher[a-z]+|Hol[a-z]+102,412.23 ns2,482.554 ns1.00-NA
CountPR(?i)Sher[a-z]+|Hol[a-z]+100,226.97 ns4,693.052 ns0.98-NA
CountMain(?i)Sherlock63,157.23 ns286.797 ns1.00-NA
CountPR(?i)Sherlock63,592.22 ns294.601 ns1.013 BNA
CountMain(?i)Sherlock Holmes63,163.87 ns353.487 ns1.00-NA
CountPR(?i)Sherlock Holmes63,130.32 ns312.279 ns1.00-NA
CountMain(?i)Sherlock|Holmes|Watson96,989.85 ns3,823.367 ns1.00-NA
CountPR(?i)Sherlock|Holmes|Watson96,919.46 ns4,402.650 ns1.00-NA
CountMain(?i)Sherlock|(...)er|John|Baker [49]292,458.32 ns4,255.586 ns1.002 B1.00
CountPR(?i)Sherlock|(...)er|John|Baker [49]291,038.70 ns5,906.277 ns1.002 B1.00
CountMain(?i)the380,816.71 ns448.532 ns1.001 B1.00
CountPR(?i)the378,387.61 ns597.080 ns0.991 B1.00
CountMain(?m)^Sherlock(...)rlock Holmes$ [37]80,760.72 ns4,306.860 ns1.01-NA
CountPR(?m)^Sherlock(...)rlock Holmes$ [37]82,582.68 ns3,929.177 ns1.03-NA
CountMain(?s).*51.49 ns0.230 ns1.00-NA
CountPR(?s).*51.44 ns0.201 ns1.00-NA
CountMain[^\\n]*696,503.75 ns1,189.220 ns1.002 B1.00
CountPR[^\\n]*701,777.91 ns4,947.894 ns1.012 B1.00
CountMain[a-q][^u-z]{13}x34,252.94 ns271.978 ns1.00-NA
CountPR[a-q][^u-z]{13}x32,601.06 ns1,062.765 ns0.95-NA
CountMain[a-zA-Z]+ing4,743,957.65 ns35,002.412 ns1.0021 B1.00
CountPR[a-zA-Z]+ing4,892,478.29 ns15,606.673 ns1.0321 B1.00
CountMain\b\w+n\b9,984,392.53 ns16,833.207 ns1.0044 B1.00
CountPR\b\w+n\b10,828,533.01 ns36,736.622 ns1.0839 B0.89
CountMain\p{L}10,603,931.90 ns48,819.499 ns1.0035 B1.00
CountPR\p{L}11,179,680.36 ns9,486.172 ns1.0531 B0.89
CountMain\p{Ll}10,195,145.76 ns27,272.582 ns1.0035 B1.00
CountPR\p{Ll}11,436,304.68 ns77,659.485 ns1.1235 B1.00
CountMain\p{Lu}512,487.85 ns3,951.166 ns1.002 B1.00
CountPR\p{Lu}465,932.29 ns13,751.745 ns0.911 B0.50
CountMain\s[a-zA-Z]{0,12}ing\s5,401,364.31 ns12,575.532 ns1.0024 B1.00
CountPR\s[a-zA-Z]{0,12}ing\s5,785,507.55 ns101,020.912 ns1.0724 B1.00
CountMain\w+5,177,572.11 ns28,630.119 ns1.0018 B1.00
CountPR\w+5,505,569.07 ns66,941.247 ns1.0618 B1.00
CountMain\w+\s+Holmes4,021,934.73 ns23,376.720 ns1.0022 B1.00
CountPR\w+\s+Holmes4,287,127.11 ns34,628.196 ns1.0722 B1.00
CountMain\w+\s+Holmes\s+\w+4,157,736.06 ns3,369.514 ns1.0023 B1.00
CountPR\w+\s+Holmes\s+\w+4,448,197.47 ns8,704.825 ns1.0723 B1.00
CountMainaei60,226.44 ns177.769 ns1.00-NA
CountPRaei59,984.97 ns231.105 ns1.00-NA
CountMainaqj60,359.02 ns219.068 ns1.00-NA
CountPRaqj60,216.79 ns250.061 ns1.00-NA
CountMainHolmes70,247.90 ns381.235 ns1.00-NA
CountPRHolmes70,191.66 ns312.375 ns1.00-NA
CountMainHolmes.{0,25}(...).{0,25}Holmes [39]59,812.45 ns223.860 ns1.00-NA
CountPRHolmes.{0,25}(...).{0,25}Holmes [39]61,210.71 ns1,547.310 ns1.02-NA
CountMainSher[a-z]+|Hol[a-z]+66,397.69 ns761.073 ns1.00-NA
CountPRSher[a-z]+|Hol[a-z]+64,849.71 ns1,154.795 ns0.983 BNA
CountMainSherlock85,985.04 ns1,966.243 ns1.00-NA
CountPRSherlock83,371.97 ns3,793.039 ns0.97-NA
CountMainSherlock Holmes82,774.02 ns3,862.238 ns1.01-NA
CountPRSherlock Holmes85,172.83 ns2,128.470 ns1.03-NA
CountMainSherlock\s+Holmes83,442.70 ns3,644.738 ns1.00-NA
CountPRSherlock\s+Holmes81,539.97 ns4,064.719 ns0.98-NA
CountMainSherlock|Holmes57,513.25 ns1,431.014 ns1.00-NA
CountPRSherlock|Holmes58,628.39 ns909.981 ns1.02-NA
CountMainSherlock|Holmes|Watson81,797.43 ns3,871.627 ns1.00-NA
CountPRSherlock|Holmes|Watson77,711.13 ns263.733 ns0.95-NA
CountMainSherlock|Holm(...)er|John|Baker [45]204,100.20 ns4,644.087 ns1.001 B1.00
CountPRSherlock|Holm(...)er|John|Baker [45]209,457.96 ns1,109.672 ns1.031 B1.00
CountMainSherlock|Street34,583.11 ns1,498.786 ns1.00-NA
CountPRSherlock|Street37,804.48 ns905.387 ns1.10-NA
CountMainthe308,111.60 ns2,660.420 ns1.001 B1.00
CountPRthe304,342.71 ns867.519 ns0.991 B1.00
CountMainThe74,898.95 ns553.273 ns1.00-NA
CountPRThe74,592.77 ns544.687 ns1.00-NA
CountMainthe\s+\w+448,325.25 ns1,314.530 ns1.001 B1.00
CountPRthe\s+\w+457,653.52 ns8,459.813 ns1.021 B1.00
CountMainzqj59,408.54 ns583.905 ns1.00-NA
CountPRzqj59,892.80 ns549.900 ns1.01-NA

A few other runs

public BitVector256 Lookup = lookup;

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly Vector128<byte> Bitmap128() => Bitmap512._lower._lower;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: why a method rather than a property?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a bit more code to define the get since we need the MethodImpl on it. No other reason.

public struct AsciiState(Vector128<byte> bitmap, BitVector256 lookup)
{
public Vector256<byte> Bitmap = Vector256.Create(bitmap);
public Vector512<byte> Bitmap512 = Vector512.Create(bitmap);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These can't / shouldn't be readonly?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The TryIndexOfAny helpers (called by non-searchvalues IndexOfAny) are writing into this field directly when computing the bitmap to avoid needing an extra local.
As far as the vectorized code is concerned, these could be readonly.

@MihaZupan
MihaZupan merged commit ce1ae77 into dotnet:mainJun 22, 2024
rzikm pushed a commit to rzikm/dotnet-runtime that referenced this pull request Jun 24, 2024
MihaZupan added a commit to MihaZupan/runtime that referenced this pull request Jul 10, 2024
MihaZupan added a commit that referenced this pull request Jul 10, 2024
…4688)
* Revert "Add Avx512 support to IndexOfAnyAsciiSearcher (#103710)"
This reverts commit ce1ae77.
* Keep the test improvements
* Keep the inlining changes
* Keep the shift improvements
matouskozak added a commit to matouskozak/runtime that referenced this pull request Jul 11, 2024
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jul 23, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Light up IndexOfAnyAsciiSearcher for AVX512

3 participants

@MihaZupan@MihuBot@stephentoub
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Add Avx512 support to IndexOfAnyAsciiSearcher - #103710

Merged
MihaZupan merged 1 commit into
dotnet:mainfrom
MihaZupan:searchvalues-ascii-avx512-5
Jun 22, 2024
Merged

Add Avx512 support to IndexOfAnyAsciiSearcher#103710
MihaZupan merged 1 commit into
dotnet:mainfrom
MihaZupan:searchvalues-ascii-avx512-5

Conversation

@MihaZupan

Copy link
Copy Markdown
Member

Closes#93222

Pretty much a copy-paste of the existing Vector128/Vector256 paths (#93222 (comment)).
I had to spam a couple more AggressiveInlinings to get all the small helpers to inline even in microbenchmarks where they're never called. This is the source of slight improvements for early matches in a couple benchmarks below.

Numbers-wise it's a ~0.5 - 1 ns regression for early matches, and a speedup to ~1.5x in throughput for longer inputs.

Early matches
MethodToolchainLengthMatchAtStartMeanErrorRatio
IndexOfAny_Charmain32True4.885 ns0.0129 ns1.00
IndexOfAny_Charpr32True3.343 ns0.0007 ns0.68
IndexOfAnyExcept_Charmain32True3.056 ns0.0008 ns1.00
IndexOfAnyExcept_Charpr32True3.152 ns0.0095 ns1.03
LastIndexOfAny_Charmain32True4.166 ns0.0522 ns1.00
LastIndexOfAny_Charpr32True3.564 ns0.0748 ns0.86
LastIndexOfAnyExcept_Charmain32True3.550 ns0.0008 ns1.00
LastIndexOfAnyExcept_Charpr32True3.561 ns0.0007 ns1.00
IndexOfAny_Charmain33True3.463 ns0.0023 ns1.00
IndexOfAny_Charpr33True3.598 ns0.0037 ns1.04
IndexOfAnyExcept_Charmain33True2.834 ns0.0106 ns1.00
IndexOfAnyExcept_Charpr33True3.660 ns0.0064 ns1.29
LastIndexOfAny_Charmain33True4.158 ns0.0082 ns1.00
LastIndexOfAny_Charpr33True3.951 ns0.0004 ns0.95
LastIndexOfAnyExcept_Charmain33True3.162 ns0.0053 ns1.00
LastIndexOfAnyExcept_Charpr33True4.114 ns0.0006 ns1.30
IndexOfAny_Charmain65True3.464 ns0.0028 ns1.00
IndexOfAny_Charpr65True3.504 ns0.0768 ns1.01
IndexOfAnyExcept_Charmain65True2.833 ns0.0137 ns1.00
IndexOfAnyExcept_Charpr65True3.581 ns0.1278 ns1.26
LastIndexOfAny_Charmain65True4.128 ns0.0257 ns1.00
LastIndexOfAny_Charpr65True3.402 ns0.0005 ns0.82
LastIndexOfAnyExcept_Charmain65True3.030 ns0.0152 ns1.00
LastIndexOfAnyExcept_Charpr65True3.457 ns0.0019 ns1.14
IndexOfAny_Charmain10000True3.466 ns0.0035 ns1.00
IndexOfAny_Charpr10000True3.397 ns0.0004 ns0.98
IndexOfAnyExcept_Charmain10000True2.822 ns0.0111 ns1.00
IndexOfAnyExcept_Charpr10000True3.402 ns0.0012 ns1.20
LastIndexOfAny_Charmain10000True3.846 ns0.0118 ns1.00
LastIndexOfAny_Charpr10000True3.806 ns0.0153 ns0.99
LastIndexOfAnyExcept_Charmain10000True3.030 ns0.0044 ns1.00
LastIndexOfAnyExcept_Charpr10000True3.467 ns0.0014 ns1.14
Throughput
MethodToolchainLengthMatchAtStartMeanErrorRatio
IndexOfAny_Charmain32False3.109 ns0.0027 ns1.00
IndexOfAny_Charpr32False2.625 ns0.0006 ns0.84
IndexOfAnyExcept_Charmain32False2.460 ns0.0025 ns1.00
IndexOfAnyExcept_Charpr32False3.084 ns0.0783 ns1.25
LastIndexOfAny_Charmain32False3.063 ns0.0087 ns1.00
LastIndexOfAny_Charpr32False2.865 ns0.1573 ns0.94
LastIndexOfAnyExcept_Charmain32False3.646 ns0.4223 ns1.00
LastIndexOfAnyExcept_Charpr32False2.426 ns0.0036 ns0.68
IndexOfAny_Charmain33False4.343 ns0.0232 ns1.00
IndexOfAny_Charpr33False3.146 ns0.0026 ns0.72
IndexOfAnyExcept_Charmain33False4.320 ns0.2929 ns1.00
IndexOfAnyExcept_Charpr33False3.038 ns0.0004 ns0.71
LastIndexOfAny_Charmain33False4.913 ns0.0303 ns1.00
LastIndexOfAny_Charpr33False3.017 ns0.0008 ns0.61
LastIndexOfAnyExcept_Charmain33False3.896 ns0.0007 ns1.00
LastIndexOfAnyExcept_Charpr33False3.440 ns0.0003 ns0.88
IndexOfAny_Charmain65False5.708 ns0.0108 ns1.00
IndexOfAny_Charpr65False4.236 ns0.0008 ns0.74
IndexOfAnyExcept_Charmain65False5.004 ns0.0600 ns1.00
IndexOfAnyExcept_Charpr65False4.259 ns0.0068 ns0.85
LastIndexOfAny_Charmain65False6.250 ns0.1711 ns1.00
LastIndexOfAny_Charpr65False4.242 ns0.0043 ns0.68
LastIndexOfAnyExcept_Charmain65False6.590 ns0.7326 ns1.00
LastIndexOfAnyExcept_Charpr65False4.174 ns0.0598 ns0.65
IndexOfAny_Charmain10000False331.894 ns0.2110 ns1.00
IndexOfAny_Charpr10000False208.743 ns0.0179 ns0.63
IndexOfAnyExcept_Charmain10000False375.454 ns0.0229 ns1.00
IndexOfAnyExcept_Charpr10000False260.705 ns0.0650 ns0.69
LastIndexOfAny_Charmain10000False333.720 ns0.0841 ns1.00
LastIndexOfAny_Charpr10000False209.806 ns0.0891 ns0.63
LastIndexOfAnyExcept_Charmain10000False378.696 ns0.3796 ns1.00
LastIndexOfAnyExcept_Charpr10000False262.419 ns0.4015 ns0.69

I'll rerun the Regex benchmarks.

@MihaZupan

Copy link
Copy Markdown
MemberAuthor

@MihuBot benchmark Regex

@MihuBot

MihuBot commented Jun 20, 2024

Copy link
Copy Markdown
System.Text.RegularExpressions.Tests.Perf_Regex_Industry_RustLang_Sherlock
BenchmarkDotNet v0.13.13-nightly.20240311.145, Ubuntu 22.04.4 LTS (Jammy Jellyfish)
Intel Xeon Platinum 8370C CPU 2.80GHz, 1 CPU, 8 logical and 4 physical cores
MediumRun : .NET 9.0.0 (42.42.42.42424), X64 RyuJIT AVX-512F+CD+BW+DQ+VL+VBMI
Job=MediumRun OutlierMode=DontRemove IterationCount=15
LaunchCount=2 MemoryRandomization=True WarmupCount=10
MethodToolchainPatternMeanErrorRatioAllocatedAlloc Ratio
CountMain.*691,131.27 ns842.077 ns1.002 B1.00
CountPR.*701,291.96 ns4,208.201 ns1.012 B1.00
CountMain(?i)Holmes71,847.44 ns471.748 ns1.00-NA
CountPR(?i)Holmes72,181.78 ns346.591 ns1.00-NA
CountMain(?i)Sher[a-z]+|Hol[a-z]+102,412.23 ns2,482.554 ns1.00-NA
CountPR(?i)Sher[a-z]+|Hol[a-z]+100,226.97 ns4,693.052 ns0.98-NA
CountMain(?i)Sherlock63,157.23 ns286.797 ns1.00-NA
CountPR(?i)Sherlock63,592.22 ns294.601 ns1.013 BNA
CountMain(?i)Sherlock Holmes63,163.87 ns353.487 ns1.00-NA
CountPR(?i)Sherlock Holmes63,130.32 ns312.279 ns1.00-NA
CountMain(?i)Sherlock|Holmes|Watson96,989.85 ns3,823.367 ns1.00-NA
CountPR(?i)Sherlock|Holmes|Watson96,919.46 ns4,402.650 ns1.00-NA
CountMain(?i)Sherlock|(...)er|John|Baker [49]292,458.32 ns4,255.586 ns1.002 B1.00
CountPR(?i)Sherlock|(...)er|John|Baker [49]291,038.70 ns5,906.277 ns1.002 B1.00
CountMain(?i)the380,816.71 ns448.532 ns1.001 B1.00
CountPR(?i)the378,387.61 ns597.080 ns0.991 B1.00
CountMain(?m)^Sherlock(...)rlock Holmes$ [37]80,760.72 ns4,306.860 ns1.01-NA
CountPR(?m)^Sherlock(...)rlock Holmes$ [37]82,582.68 ns3,929.177 ns1.03-NA
CountMain(?s).*51.49 ns0.230 ns1.00-NA
CountPR(?s).*51.44 ns0.201 ns1.00-NA
CountMain[^\\n]*696,503.75 ns1,189.220 ns1.002 B1.00
CountPR[^\\n]*701,777.91 ns4,947.894 ns1.012 B1.00
CountMain[a-q][^u-z]{13}x34,252.94 ns271.978 ns1.00-NA
CountPR[a-q][^u-z]{13}x32,601.06 ns1,062.765 ns0.95-NA
CountMain[a-zA-Z]+ing4,743,957.65 ns35,002.412 ns1.0021 B1.00
CountPR[a-zA-Z]+ing4,892,478.29 ns15,606.673 ns1.0321 B1.00
CountMain\b\w+n\b9,984,392.53 ns16,833.207 ns1.0044 B1.00
CountPR\b\w+n\b10,828,533.01 ns36,736.622 ns1.0839 B0.89
CountMain\p{L}10,603,931.90 ns48,819.499 ns1.0035 B1.00
CountPR\p{L}11,179,680.36 ns9,486.172 ns1.0531 B0.89
CountMain\p{Ll}10,195,145.76 ns27,272.582 ns1.0035 B1.00
CountPR\p{Ll}11,436,304.68 ns77,659.485 ns1.1235 B1.00
CountMain\p{Lu}512,487.85 ns3,951.166 ns1.002 B1.00
CountPR\p{Lu}465,932.29 ns13,751.745 ns0.911 B0.50
CountMain\s[a-zA-Z]{0,12}ing\s5,401,364.31 ns12,575.532 ns1.0024 B1.00
CountPR\s[a-zA-Z]{0,12}ing\s5,785,507.55 ns101,020.912 ns1.0724 B1.00
CountMain\w+5,177,572.11 ns28,630.119 ns1.0018 B1.00
CountPR\w+5,505,569.07 ns66,941.247 ns1.0618 B1.00
CountMain\w+\s+Holmes4,021,934.73 ns23,376.720 ns1.0022 B1.00
CountPR\w+\s+Holmes4,287,127.11 ns34,628.196 ns1.0722 B1.00
CountMain\w+\s+Holmes\s+\w+4,157,736.06 ns3,369.514 ns1.0023 B1.00
CountPR\w+\s+Holmes\s+\w+4,448,197.47 ns8,704.825 ns1.0723 B1.00
CountMainaei60,226.44 ns177.769 ns1.00-NA
CountPRaei59,984.97 ns231.105 ns1.00-NA
CountMainaqj60,359.02 ns219.068 ns1.00-NA
CountPRaqj60,216.79 ns250.061 ns1.00-NA
CountMainHolmes70,247.90 ns381.235 ns1.00-NA
CountPRHolmes70,191.66 ns312.375 ns1.00-NA
CountMainHolmes.{0,25}(...).{0,25}Holmes [39]59,812.45 ns223.860 ns1.00-NA
CountPRHolmes.{0,25}(...).{0,25}Holmes [39]61,210.71 ns1,547.310 ns1.02-NA
CountMainSher[a-z]+|Hol[a-z]+66,397.69 ns761.073 ns1.00-NA
CountPRSher[a-z]+|Hol[a-z]+64,849.71 ns1,154.795 ns0.983 BNA
CountMainSherlock85,985.04 ns1,966.243 ns1.00-NA
CountPRSherlock83,371.97 ns3,793.039 ns0.97-NA
CountMainSherlock Holmes82,774.02 ns3,862.238 ns1.01-NA
CountPRSherlock Holmes85,172.83 ns2,128.470 ns1.03-NA
CountMainSherlock\s+Holmes83,442.70 ns3,644.738 ns1.00-NA
CountPRSherlock\s+Holmes81,539.97 ns4,064.719 ns0.98-NA
CountMainSherlock|Holmes57,513.25 ns1,431.014 ns1.00-NA
CountPRSherlock|Holmes58,628.39 ns909.981 ns1.02-NA
CountMainSherlock|Holmes|Watson81,797.43 ns3,871.627 ns1.00-NA
CountPRSherlock|Holmes|Watson77,711.13 ns263.733 ns0.95-NA
CountMainSherlock|Holm(...)er|John|Baker [45]204,100.20 ns4,644.087 ns1.001 B1.00
CountPRSherlock|Holm(...)er|John|Baker [45]209,457.96 ns1,109.672 ns1.031 B1.00
CountMainSherlock|Street34,583.11 ns1,498.786 ns1.00-NA
CountPRSherlock|Street37,804.48 ns905.387 ns1.10-NA
CountMainthe308,111.60 ns2,660.420 ns1.001 B1.00
CountPRthe304,342.71 ns867.519 ns0.991 B1.00
CountMainThe74,898.95 ns553.273 ns1.00-NA
CountPRThe74,592.77 ns544.687 ns1.00-NA
CountMainthe\s+\w+448,325.25 ns1,314.530 ns1.001 B1.00
CountPRthe\s+\w+457,653.52 ns8,459.813 ns1.021 B1.00
CountMainzqj59,408.54 ns583.905 ns1.00-NA
CountPRzqj59,892.80 ns549.900 ns1.01-NA

A few other runs

public BitVector256 Lookup = lookup;

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly Vector128<byte> Bitmap128() => Bitmap512._lower._lower;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: why a method rather than a property?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a bit more code to define the get since we need the MethodImpl on it. No other reason.

public struct AsciiState(Vector128<byte> bitmap, BitVector256 lookup)
{
public Vector256<byte> Bitmap = Vector256.Create(bitmap);
public Vector512<byte> Bitmap512 = Vector512.Create(bitmap);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These can't / shouldn't be readonly?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The TryIndexOfAny helpers (called by non-searchvalues IndexOfAny) are writing into this field directly when computing the bitmap to avoid needing an extra local.
As far as the vectorized code is concerned, these could be readonly.

@MihaZupan
MihaZupan merged commit ce1ae77 into dotnet:mainJun 22, 2024
rzikm pushed a commit to rzikm/dotnet-runtime that referenced this pull request Jun 24, 2024
MihaZupan added a commit to MihaZupan/runtime that referenced this pull request Jul 10, 2024
MihaZupan added a commit that referenced this pull request Jul 10, 2024
…4688)
* Revert "Add Avx512 support to IndexOfAnyAsciiSearcher (#103710)"
This reverts commit ce1ae77.
* Keep the test improvements
* Keep the inlining changes
* Keep the shift improvements
matouskozak added a commit to matouskozak/runtime that referenced this pull request Jul 11, 2024
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jul 23, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Light up IndexOfAnyAsciiSearcher for AVX512

3 participants

@MihaZupan@MihuBot@stephentoub
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Add Avx512 support to IndexOfAnyAsciiSearcher - #103710

Merged
MihaZupan merged 1 commit into
dotnet:mainfrom
MihaZupan:searchvalues-ascii-avx512-5
Jun 22, 2024
Merged

Add Avx512 support to IndexOfAnyAsciiSearcher#103710
MihaZupan merged 1 commit into
dotnet:mainfrom
MihaZupan:searchvalues-ascii-avx512-5

Conversation

@MihaZupan

Copy link
Copy Markdown
Member

Closes#93222

Pretty much a copy-paste of the existing Vector128/Vector256 paths (#93222 (comment)).
I had to spam a couple more AggressiveInlinings to get all the small helpers to inline even in microbenchmarks where they're never called. This is the source of slight improvements for early matches in a couple benchmarks below.

Numbers-wise it's a ~0.5 - 1 ns regression for early matches, and a speedup to ~1.5x in throughput for longer inputs.

Early matches
MethodToolchainLengthMatchAtStartMeanErrorRatio
IndexOfAny_Charmain32True4.885 ns0.0129 ns1.00
IndexOfAny_Charpr32True3.343 ns0.0007 ns0.68
IndexOfAnyExcept_Charmain32True3.056 ns0.0008 ns1.00
IndexOfAnyExcept_Charpr32True3.152 ns0.0095 ns1.03
LastIndexOfAny_Charmain32True4.166 ns0.0522 ns1.00
LastIndexOfAny_Charpr32True3.564 ns0.0748 ns0.86
LastIndexOfAnyExcept_Charmain32True3.550 ns0.0008 ns1.00
LastIndexOfAnyExcept_Charpr32True3.561 ns0.0007 ns1.00
IndexOfAny_Charmain33True3.463 ns0.0023 ns1.00
IndexOfAny_Charpr33True3.598 ns0.0037 ns1.04
IndexOfAnyExcept_Charmain33True2.834 ns0.0106 ns1.00
IndexOfAnyExcept_Charpr33True3.660 ns0.0064 ns1.29
LastIndexOfAny_Charmain33True4.158 ns0.0082 ns1.00
LastIndexOfAny_Charpr33True3.951 ns0.0004 ns0.95
LastIndexOfAnyExcept_Charmain33True3.162 ns0.0053 ns1.00
LastIndexOfAnyExcept_Charpr33True4.114 ns0.0006 ns1.30
IndexOfAny_Charmain65True3.464 ns0.0028 ns1.00
IndexOfAny_Charpr65True3.504 ns0.0768 ns1.01
IndexOfAnyExcept_Charmain65True2.833 ns0.0137 ns1.00
IndexOfAnyExcept_Charpr65True3.581 ns0.1278 ns1.26
LastIndexOfAny_Charmain65True4.128 ns0.0257 ns1.00
LastIndexOfAny_Charpr65True3.402 ns0.0005 ns0.82
LastIndexOfAnyExcept_Charmain65True3.030 ns0.0152 ns1.00
LastIndexOfAnyExcept_Charpr65True3.457 ns0.0019 ns1.14
IndexOfAny_Charmain10000True3.466 ns0.0035 ns1.00
IndexOfAny_Charpr10000True3.397 ns0.0004 ns0.98
IndexOfAnyExcept_Charmain10000True2.822 ns0.0111 ns1.00
IndexOfAnyExcept_Charpr10000True3.402 ns0.0012 ns1.20
LastIndexOfAny_Charmain10000True3.846 ns0.0118 ns1.00
LastIndexOfAny_Charpr10000True3.806 ns0.0153 ns0.99
LastIndexOfAnyExcept_Charmain10000True3.030 ns0.0044 ns1.00
LastIndexOfAnyExcept_Charpr10000True3.467 ns0.0014 ns1.14
Throughput
MethodToolchainLengthMatchAtStartMeanErrorRatio
IndexOfAny_Charmain32False3.109 ns0.0027 ns1.00
IndexOfAny_Charpr32False2.625 ns0.0006 ns0.84
IndexOfAnyExcept_Charmain32False2.460 ns0.0025 ns1.00
IndexOfAnyExcept_Charpr32False3.084 ns0.0783 ns1.25
LastIndexOfAny_Charmain32False3.063 ns0.0087 ns1.00
LastIndexOfAny_Charpr32False2.865 ns0.1573 ns0.94
LastIndexOfAnyExcept_Charmain32False3.646 ns0.4223 ns1.00
LastIndexOfAnyExcept_Charpr32False2.426 ns0.0036 ns0.68
IndexOfAny_Charmain33False4.343 ns0.0232 ns1.00
IndexOfAny_Charpr33False3.146 ns0.0026 ns0.72
IndexOfAnyExcept_Charmain33False4.320 ns0.2929 ns1.00
IndexOfAnyExcept_Charpr33False3.038 ns0.0004 ns0.71
LastIndexOfAny_Charmain33False4.913 ns0.0303 ns1.00
LastIndexOfAny_Charpr33False3.017 ns0.0008 ns0.61
LastIndexOfAnyExcept_Charmain33False3.896 ns0.0007 ns1.00
LastIndexOfAnyExcept_Charpr33False3.440 ns0.0003 ns0.88
IndexOfAny_Charmain65False5.708 ns0.0108 ns1.00
IndexOfAny_Charpr65False4.236 ns0.0008 ns0.74
IndexOfAnyExcept_Charmain65False5.004 ns0.0600 ns1.00
IndexOfAnyExcept_Charpr65False4.259 ns0.0068 ns0.85
LastIndexOfAny_Charmain65False6.250 ns0.1711 ns1.00
LastIndexOfAny_Charpr65False4.242 ns0.0043 ns0.68
LastIndexOfAnyExcept_Charmain65False6.590 ns0.7326 ns1.00
LastIndexOfAnyExcept_Charpr65False4.174 ns0.0598 ns0.65
IndexOfAny_Charmain10000False331.894 ns0.2110 ns1.00
IndexOfAny_Charpr10000False208.743 ns0.0179 ns0.63
IndexOfAnyExcept_Charmain10000False375.454 ns0.0229 ns1.00
IndexOfAnyExcept_Charpr10000False260.705 ns0.0650 ns0.69
LastIndexOfAny_Charmain10000False333.720 ns0.0841 ns1.00
LastIndexOfAny_Charpr10000False209.806 ns0.0891 ns0.63
LastIndexOfAnyExcept_Charmain10000False378.696 ns0.3796 ns1.00
LastIndexOfAnyExcept_Charpr10000False262.419 ns0.4015 ns0.69

I'll rerun the Regex benchmarks.

@MihaZupan

Copy link
Copy Markdown
MemberAuthor

@MihuBot benchmark Regex

@MihuBot

MihuBot commented Jun 20, 2024

Copy link
Copy Markdown
System.Text.RegularExpressions.Tests.Perf_Regex_Industry_RustLang_Sherlock
BenchmarkDotNet v0.13.13-nightly.20240311.145, Ubuntu 22.04.4 LTS (Jammy Jellyfish)
Intel Xeon Platinum 8370C CPU 2.80GHz, 1 CPU, 8 logical and 4 physical cores
MediumRun : .NET 9.0.0 (42.42.42.42424), X64 RyuJIT AVX-512F+CD+BW+DQ+VL+VBMI
Job=MediumRun OutlierMode=DontRemove IterationCount=15
LaunchCount=2 MemoryRandomization=True WarmupCount=10
MethodToolchainPatternMeanErrorRatioAllocatedAlloc Ratio
CountMain.*691,131.27 ns842.077 ns1.002 B1.00
CountPR.*701,291.96 ns4,208.201 ns1.012 B1.00
CountMain(?i)Holmes71,847.44 ns471.748 ns1.00-NA
CountPR(?i)Holmes72,181.78 ns346.591 ns1.00-NA
CountMain(?i)Sher[a-z]+|Hol[a-z]+102,412.23 ns2,482.554 ns1.00-NA
CountPR(?i)Sher[a-z]+|Hol[a-z]+100,226.97 ns4,693.052 ns0.98-NA
CountMain(?i)Sherlock63,157.23 ns286.797 ns1.00-NA
CountPR(?i)Sherlock63,592.22 ns294.601 ns1.013 BNA
CountMain(?i)Sherlock Holmes63,163.87 ns353.487 ns1.00-NA
CountPR(?i)Sherlock Holmes63,130.32 ns312.279 ns1.00-NA
CountMain(?i)Sherlock|Holmes|Watson96,989.85 ns3,823.367 ns1.00-NA
CountPR(?i)Sherlock|Holmes|Watson96,919.46 ns4,402.650 ns1.00-NA
CountMain(?i)Sherlock|(...)er|John|Baker [49]292,458.32 ns4,255.586 ns1.002 B1.00
CountPR(?i)Sherlock|(...)er|John|Baker [49]291,038.70 ns5,906.277 ns1.002 B1.00
CountMain(?i)the380,816.71 ns448.532 ns1.001 B1.00
CountPR(?i)the378,387.61 ns597.080 ns0.991 B1.00
CountMain(?m)^Sherlock(...)rlock Holmes$ [37]80,760.72 ns4,306.860 ns1.01-NA
CountPR(?m)^Sherlock(...)rlock Holmes$ [37]82,582.68 ns3,929.177 ns1.03-NA
CountMain(?s).*51.49 ns0.230 ns1.00-NA
CountPR(?s).*51.44 ns0.201 ns1.00-NA
CountMain[^\\n]*696,503.75 ns1,189.220 ns1.002 B1.00
CountPR[^\\n]*701,777.91 ns4,947.894 ns1.012 B1.00
CountMain[a-q][^u-z]{13}x34,252.94 ns271.978 ns1.00-NA
CountPR[a-q][^u-z]{13}x32,601.06 ns1,062.765 ns0.95-NA
CountMain[a-zA-Z]+ing4,743,957.65 ns35,002.412 ns1.0021 B1.00
CountPR[a-zA-Z]+ing4,892,478.29 ns15,606.673 ns1.0321 B1.00
CountMain\b\w+n\b9,984,392.53 ns16,833.207 ns1.0044 B1.00
CountPR\b\w+n\b10,828,533.01 ns36,736.622 ns1.0839 B0.89
CountMain\p{L}10,603,931.90 ns48,819.499 ns1.0035 B1.00
CountPR\p{L}11,179,680.36 ns9,486.172 ns1.0531 B0.89
CountMain\p{Ll}10,195,145.76 ns27,272.582 ns1.0035 B1.00
CountPR\p{Ll}11,436,304.68 ns77,659.485 ns1.1235 B1.00
CountMain\p{Lu}512,487.85 ns3,951.166 ns1.002 B1.00
CountPR\p{Lu}465,932.29 ns13,751.745 ns0.911 B0.50
CountMain\s[a-zA-Z]{0,12}ing\s5,401,364.31 ns12,575.532 ns1.0024 B1.00
CountPR\s[a-zA-Z]{0,12}ing\s5,785,507.55 ns101,020.912 ns1.0724 B1.00
CountMain\w+5,177,572.11 ns28,630.119 ns1.0018 B1.00
CountPR\w+5,505,569.07 ns66,941.247 ns1.0618 B1.00
CountMain\w+\s+Holmes4,021,934.73 ns23,376.720 ns1.0022 B1.00
CountPR\w+\s+Holmes4,287,127.11 ns34,628.196 ns1.0722 B1.00
CountMain\w+\s+Holmes\s+\w+4,157,736.06 ns3,369.514 ns1.0023 B1.00
CountPR\w+\s+Holmes\s+\w+4,448,197.47 ns8,704.825 ns1.0723 B1.00
CountMainaei60,226.44 ns177.769 ns1.00-NA
CountPRaei59,984.97 ns231.105 ns1.00-NA
CountMainaqj60,359.02 ns219.068 ns1.00-NA
CountPRaqj60,216.79 ns250.061 ns1.00-NA
CountMainHolmes70,247.90 ns381.235 ns1.00-NA
CountPRHolmes70,191.66 ns312.375 ns1.00-NA
CountMainHolmes.{0,25}(...).{0,25}Holmes [39]59,812.45 ns223.860 ns1.00-NA
CountPRHolmes.{0,25}(...).{0,25}Holmes [39]61,210.71 ns1,547.310 ns1.02-NA
CountMainSher[a-z]+|Hol[a-z]+66,397.69 ns761.073 ns1.00-NA
CountPRSher[a-z]+|Hol[a-z]+64,849.71 ns1,154.795 ns0.983 BNA
CountMainSherlock85,985.04 ns1,966.243 ns1.00-NA
CountPRSherlock83,371.97 ns3,793.039 ns0.97-NA
CountMainSherlock Holmes82,774.02 ns3,862.238 ns1.01-NA
CountPRSherlock Holmes85,172.83 ns2,128.470 ns1.03-NA
CountMainSherlock\s+Holmes83,442.70 ns3,644.738 ns1.00-NA
CountPRSherlock\s+Holmes81,539.97 ns4,064.719 ns0.98-NA
CountMainSherlock|Holmes57,513.25 ns1,431.014 ns1.00-NA
CountPRSherlock|Holmes58,628.39 ns909.981 ns1.02-NA
CountMainSherlock|Holmes|Watson81,797.43 ns3,871.627 ns1.00-NA
CountPRSherlock|Holmes|Watson77,711.13 ns263.733 ns0.95-NA
CountMainSherlock|Holm(...)er|John|Baker [45]204,100.20 ns4,644.087 ns1.001 B1.00
CountPRSherlock|Holm(...)er|John|Baker [45]209,457.96 ns1,109.672 ns1.031 B1.00
CountMainSherlock|Street34,583.11 ns1,498.786 ns1.00-NA
CountPRSherlock|Street37,804.48 ns905.387 ns1.10-NA
CountMainthe308,111.60 ns2,660.420 ns1.001 B1.00
CountPRthe304,342.71 ns867.519 ns0.991 B1.00
CountMainThe74,898.95 ns553.273 ns1.00-NA
CountPRThe74,592.77 ns544.687 ns1.00-NA
CountMainthe\s+\w+448,325.25 ns1,314.530 ns1.001 B1.00
CountPRthe\s+\w+457,653.52 ns8,459.813 ns1.021 B1.00
CountMainzqj59,408.54 ns583.905 ns1.00-NA
CountPRzqj59,892.80 ns549.900 ns1.01-NA

A few other runs

public BitVector256 Lookup = lookup;

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly Vector128<byte> Bitmap128() => Bitmap512._lower._lower;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: why a method rather than a property?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a bit more code to define the get since we need the MethodImpl on it. No other reason.

public struct AsciiState(Vector128<byte> bitmap, BitVector256 lookup)
{
public Vector256<byte> Bitmap = Vector256.Create(bitmap);
public Vector512<byte> Bitmap512 = Vector512.Create(bitmap);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These can't / shouldn't be readonly?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The TryIndexOfAny helpers (called by non-searchvalues IndexOfAny) are writing into this field directly when computing the bitmap to avoid needing an extra local.
As far as the vectorized code is concerned, these could be readonly.

@MihaZupan
MihaZupan merged commit ce1ae77 into dotnet:mainJun 22, 2024
rzikm pushed a commit to rzikm/dotnet-runtime that referenced this pull request Jun 24, 2024
MihaZupan added a commit to MihaZupan/runtime that referenced this pull request Jul 10, 2024
MihaZupan added a commit that referenced this pull request Jul 10, 2024
…4688)
* Revert "Add Avx512 support to IndexOfAnyAsciiSearcher (#103710)"
This reverts commit ce1ae77.
* Keep the test improvements
* Keep the inlining changes
* Keep the shift improvements
matouskozak added a commit to matouskozak/runtime that referenced this pull request Jul 11, 2024
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jul 23, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Light up IndexOfAnyAsciiSearcher for AVX512

3 participants

@MihaZupan@MihuBot@stephentoub
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Add Avx512 support to IndexOfAnyAsciiSearcher - #103710

Merged
MihaZupan merged 1 commit into
dotnet:mainfrom
MihaZupan:searchvalues-ascii-avx512-5
Jun 22, 2024
Merged

Add Avx512 support to IndexOfAnyAsciiSearcher#103710
MihaZupan merged 1 commit into
dotnet:mainfrom
MihaZupan:searchvalues-ascii-avx512-5

Conversation

@MihaZupan

Copy link
Copy Markdown
Member

Closes#93222

Pretty much a copy-paste of the existing Vector128/Vector256 paths (#93222 (comment)).
I had to spam a couple more AggressiveInlinings to get all the small helpers to inline even in microbenchmarks where they're never called. This is the source of slight improvements for early matches in a couple benchmarks below.

Numbers-wise it's a ~0.5 - 1 ns regression for early matches, and a speedup to ~1.5x in throughput for longer inputs.

Early matches
MethodToolchainLengthMatchAtStartMeanErrorRatio
IndexOfAny_Charmain32True4.885 ns0.0129 ns1.00
IndexOfAny_Charpr32True3.343 ns0.0007 ns0.68
IndexOfAnyExcept_Charmain32True3.056 ns0.0008 ns1.00
IndexOfAnyExcept_Charpr32True3.152 ns0.0095 ns1.03
LastIndexOfAny_Charmain32True4.166 ns0.0522 ns1.00
LastIndexOfAny_Charpr32True3.564 ns0.0748 ns0.86
LastIndexOfAnyExcept_Charmain32True3.550 ns0.0008 ns1.00
LastIndexOfAnyExcept_Charpr32True3.561 ns0.0007 ns1.00
IndexOfAny_Charmain33True3.463 ns0.0023 ns1.00
IndexOfAny_Charpr33True3.598 ns0.0037 ns1.04
IndexOfAnyExcept_Charmain33True2.834 ns0.0106 ns1.00
IndexOfAnyExcept_Charpr33True3.660 ns0.0064 ns1.29
LastIndexOfAny_Charmain33True4.158 ns0.0082 ns1.00
LastIndexOfAny_Charpr33True3.951 ns0.0004 ns0.95
LastIndexOfAnyExcept_Charmain33True3.162 ns0.0053 ns1.00
LastIndexOfAnyExcept_Charpr33True4.114 ns0.0006 ns1.30
IndexOfAny_Charmain65True3.464 ns0.0028 ns1.00
IndexOfAny_Charpr65True3.504 ns0.0768 ns1.01
IndexOfAnyExcept_Charmain65True2.833 ns0.0137 ns1.00
IndexOfAnyExcept_Charpr65True3.581 ns0.1278 ns1.26
LastIndexOfAny_Charmain65True4.128 ns0.0257 ns1.00
LastIndexOfAny_Charpr65True3.402 ns0.0005 ns0.82
LastIndexOfAnyExcept_Charmain65True3.030 ns0.0152 ns1.00
LastIndexOfAnyExcept_Charpr65True3.457 ns0.0019 ns1.14
IndexOfAny_Charmain10000True3.466 ns0.0035 ns1.00
IndexOfAny_Charpr10000True3.397 ns0.0004 ns0.98
IndexOfAnyExcept_Charmain10000True2.822 ns0.0111 ns1.00
IndexOfAnyExcept_Charpr10000True3.402 ns0.0012 ns1.20
LastIndexOfAny_Charmain10000True3.846 ns0.0118 ns1.00
LastIndexOfAny_Charpr10000True3.806 ns0.0153 ns0.99
LastIndexOfAnyExcept_Charmain10000True3.030 ns0.0044 ns1.00
LastIndexOfAnyExcept_Charpr10000True3.467 ns0.0014 ns1.14
Throughput
MethodToolchainLengthMatchAtStartMeanErrorRatio
IndexOfAny_Charmain32False3.109 ns0.0027 ns1.00
IndexOfAny_Charpr32False2.625 ns0.0006 ns0.84
IndexOfAnyExcept_Charmain32False2.460 ns0.0025 ns1.00
IndexOfAnyExcept_Charpr32False3.084 ns0.0783 ns1.25
LastIndexOfAny_Charmain32False3.063 ns0.0087 ns1.00
LastIndexOfAny_Charpr32False2.865 ns0.1573 ns0.94
LastIndexOfAnyExcept_Charmain32False3.646 ns0.4223 ns1.00
LastIndexOfAnyExcept_Charpr32False2.426 ns0.0036 ns0.68
IndexOfAny_Charmain33False4.343 ns0.0232 ns1.00
IndexOfAny_Charpr33False3.146 ns0.0026 ns0.72
IndexOfAnyExcept_Charmain33False4.320 ns0.2929 ns1.00
IndexOfAnyExcept_Charpr33False3.038 ns0.0004 ns0.71
LastIndexOfAny_Charmain33False4.913 ns0.0303 ns1.00
LastIndexOfAny_Charpr33False3.017 ns0.0008 ns0.61
LastIndexOfAnyExcept_Charmain33False3.896 ns0.0007 ns1.00
LastIndexOfAnyExcept_Charpr33False3.440 ns0.0003 ns0.88
IndexOfAny_Charmain65False5.708 ns0.0108 ns1.00
IndexOfAny_Charpr65False4.236 ns0.0008 ns0.74
IndexOfAnyExcept_Charmain65False5.004 ns0.0600 ns1.00
IndexOfAnyExcept_Charpr65False4.259 ns0.0068 ns0.85
LastIndexOfAny_Charmain65False6.250 ns0.1711 ns1.00
LastIndexOfAny_Charpr65False4.242 ns0.0043 ns0.68
LastIndexOfAnyExcept_Charmain65False6.590 ns0.7326 ns1.00
LastIndexOfAnyExcept_Charpr65False4.174 ns0.0598 ns0.65
IndexOfAny_Charmain10000False331.894 ns0.2110 ns1.00
IndexOfAny_Charpr10000False208.743 ns0.0179 ns0.63
IndexOfAnyExcept_Charmain10000False375.454 ns0.0229 ns1.00
IndexOfAnyExcept_Charpr10000False260.705 ns0.0650 ns0.69
LastIndexOfAny_Charmain10000False333.720 ns0.0841 ns1.00
LastIndexOfAny_Charpr10000False209.806 ns0.0891 ns0.63
LastIndexOfAnyExcept_Charmain10000False378.696 ns0.3796 ns1.00
LastIndexOfAnyExcept_Charpr10000False262.419 ns0.4015 ns0.69

I'll rerun the Regex benchmarks.

@MihaZupan

Copy link
Copy Markdown
MemberAuthor

@MihuBot benchmark Regex

@MihuBot

MihuBot commented Jun 20, 2024

Copy link
Copy Markdown
System.Text.RegularExpressions.Tests.Perf_Regex_Industry_RustLang_Sherlock
BenchmarkDotNet v0.13.13-nightly.20240311.145, Ubuntu 22.04.4 LTS (Jammy Jellyfish)
Intel Xeon Platinum 8370C CPU 2.80GHz, 1 CPU, 8 logical and 4 physical cores
MediumRun : .NET 9.0.0 (42.42.42.42424), X64 RyuJIT AVX-512F+CD+BW+DQ+VL+VBMI
Job=MediumRun OutlierMode=DontRemove IterationCount=15
LaunchCount=2 MemoryRandomization=True WarmupCount=10
MethodToolchainPatternMeanErrorRatioAllocatedAlloc Ratio
CountMain.*691,131.27 ns842.077 ns1.002 B1.00
CountPR.*701,291.96 ns4,208.201 ns1.012 B1.00
CountMain(?i)Holmes71,847.44 ns471.748 ns1.00-NA
CountPR(?i)Holmes72,181.78 ns346.591 ns1.00-NA
CountMain(?i)Sher[a-z]+|Hol[a-z]+102,412.23 ns2,482.554 ns1.00-NA
CountPR(?i)Sher[a-z]+|Hol[a-z]+100,226.97 ns4,693.052 ns0.98-NA
CountMain(?i)Sherlock63,157.23 ns286.797 ns1.00-NA
CountPR(?i)Sherlock63,592.22 ns294.601 ns1.013 BNA
CountMain(?i)Sherlock Holmes63,163.87 ns353.487 ns1.00-NA
CountPR(?i)Sherlock Holmes63,130.32 ns312.279 ns1.00-NA
CountMain(?i)Sherlock|Holmes|Watson96,989.85 ns3,823.367 ns1.00-NA
CountPR(?i)Sherlock|Holmes|Watson96,919.46 ns4,402.650 ns1.00-NA
CountMain(?i)Sherlock|(...)er|John|Baker [49]292,458.32 ns4,255.586 ns1.002 B1.00
CountPR(?i)Sherlock|(...)er|John|Baker [49]291,038.70 ns5,906.277 ns1.002 B1.00
CountMain(?i)the380,816.71 ns448.532 ns1.001 B1.00
CountPR(?i)the378,387.61 ns597.080 ns0.991 B1.00
CountMain(?m)^Sherlock(...)rlock Holmes$ [37]80,760.72 ns4,306.860 ns1.01-NA
CountPR(?m)^Sherlock(...)rlock Holmes$ [37]82,582.68 ns3,929.177 ns1.03-NA
CountMain(?s).*51.49 ns0.230 ns1.00-NA
CountPR(?s).*51.44 ns0.201 ns1.00-NA
CountMain[^\\n]*696,503.75 ns1,189.220 ns1.002 B1.00
CountPR[^\\n]*701,777.91 ns4,947.894 ns1.012 B1.00
CountMain[a-q][^u-z]{13}x34,252.94 ns271.978 ns1.00-NA
CountPR[a-q][^u-z]{13}x32,601.06 ns1,062.765 ns0.95-NA
CountMain[a-zA-Z]+ing4,743,957.65 ns35,002.412 ns1.0021 B1.00
CountPR[a-zA-Z]+ing4,892,478.29 ns15,606.673 ns1.0321 B1.00
CountMain\b\w+n\b9,984,392.53 ns16,833.207 ns1.0044 B1.00
CountPR\b\w+n\b10,828,533.01 ns36,736.622 ns1.0839 B0.89
CountMain\p{L}10,603,931.90 ns48,819.499 ns1.0035 B1.00
CountPR\p{L}11,179,680.36 ns9,486.172 ns1.0531 B0.89
CountMain\p{Ll}10,195,145.76 ns27,272.582 ns1.0035 B1.00
CountPR\p{Ll}11,436,304.68 ns77,659.485 ns1.1235 B1.00
CountMain\p{Lu}512,487.85 ns3,951.166 ns1.002 B1.00
CountPR\p{Lu}465,932.29 ns13,751.745 ns0.911 B0.50
CountMain\s[a-zA-Z]{0,12}ing\s5,401,364.31 ns12,575.532 ns1.0024 B1.00
CountPR\s[a-zA-Z]{0,12}ing\s5,785,507.55 ns101,020.912 ns1.0724 B1.00
CountMain\w+5,177,572.11 ns28,630.119 ns1.0018 B1.00
CountPR\w+5,505,569.07 ns66,941.247 ns1.0618 B1.00
CountMain\w+\s+Holmes4,021,934.73 ns23,376.720 ns1.0022 B1.00
CountPR\w+\s+Holmes4,287,127.11 ns34,628.196 ns1.0722 B1.00
CountMain\w+\s+Holmes\s+\w+4,157,736.06 ns3,369.514 ns1.0023 B1.00
CountPR\w+\s+Holmes\s+\w+4,448,197.47 ns8,704.825 ns1.0723 B1.00
CountMainaei60,226.44 ns177.769 ns1.00-NA
CountPRaei59,984.97 ns231.105 ns1.00-NA
CountMainaqj60,359.02 ns219.068 ns1.00-NA
CountPRaqj60,216.79 ns250.061 ns1.00-NA
CountMainHolmes70,247.90 ns381.235 ns1.00-NA
CountPRHolmes70,191.66 ns312.375 ns1.00-NA
CountMainHolmes.{0,25}(...).{0,25}Holmes [39]59,812.45 ns223.860 ns1.00-NA
CountPRHolmes.{0,25}(...).{0,25}Holmes [39]61,210.71 ns1,547.310 ns1.02-NA
CountMainSher[a-z]+|Hol[a-z]+66,397.69 ns761.073 ns1.00-NA
CountPRSher[a-z]+|Hol[a-z]+64,849.71 ns1,154.795 ns0.983 BNA
CountMainSherlock85,985.04 ns1,966.243 ns1.00-NA
CountPRSherlock83,371.97 ns3,793.039 ns0.97-NA
CountMainSherlock Holmes82,774.02 ns3,862.238 ns1.01-NA
CountPRSherlock Holmes85,172.83 ns2,128.470 ns1.03-NA
CountMainSherlock\s+Holmes83,442.70 ns3,644.738 ns1.00-NA
CountPRSherlock\s+Holmes81,539.97 ns4,064.719 ns0.98-NA
CountMainSherlock|Holmes57,513.25 ns1,431.014 ns1.00-NA
CountPRSherlock|Holmes58,628.39 ns909.981 ns1.02-NA
CountMainSherlock|Holmes|Watson81,797.43 ns3,871.627 ns1.00-NA
CountPRSherlock|Holmes|Watson77,711.13 ns263.733 ns0.95-NA
CountMainSherlock|Holm(...)er|John|Baker [45]204,100.20 ns4,644.087 ns1.001 B1.00
CountPRSherlock|Holm(...)er|John|Baker [45]209,457.96 ns1,109.672 ns1.031 B1.00
CountMainSherlock|Street34,583.11 ns1,498.786 ns1.00-NA
CountPRSherlock|Street37,804.48 ns905.387 ns1.10-NA
CountMainthe308,111.60 ns2,660.420 ns1.001 B1.00
CountPRthe304,342.71 ns867.519 ns0.991 B1.00
CountMainThe74,898.95 ns553.273 ns1.00-NA
CountPRThe74,592.77 ns544.687 ns1.00-NA
CountMainthe\s+\w+448,325.25 ns1,314.530 ns1.001 B1.00
CountPRthe\s+\w+457,653.52 ns8,459.813 ns1.021 B1.00
CountMainzqj59,408.54 ns583.905 ns1.00-NA
CountPRzqj59,892.80 ns549.900 ns1.01-NA

A few other runs

public BitVector256 Lookup = lookup;

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly Vector128<byte> Bitmap128() => Bitmap512._lower._lower;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: why a method rather than a property?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a bit more code to define the get since we need the MethodImpl on it. No other reason.

public struct AsciiState(Vector128<byte> bitmap, BitVector256 lookup)
{
public Vector256<byte> Bitmap = Vector256.Create(bitmap);
public Vector512<byte> Bitmap512 = Vector512.Create(bitmap);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These can't / shouldn't be readonly?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The TryIndexOfAny helpers (called by non-searchvalues IndexOfAny) are writing into this field directly when computing the bitmap to avoid needing an extra local.
As far as the vectorized code is concerned, these could be readonly.

@MihaZupan
MihaZupan merged commit ce1ae77 into dotnet:mainJun 22, 2024
rzikm pushed a commit to rzikm/dotnet-runtime that referenced this pull request Jun 24, 2024
MihaZupan added a commit to MihaZupan/runtime that referenced this pull request Jul 10, 2024
MihaZupan added a commit that referenced this pull request Jul 10, 2024
…4688)
* Revert "Add Avx512 support to IndexOfAnyAsciiSearcher (#103710)"
This reverts commit ce1ae77.
* Keep the test improvements
* Keep the inlining changes
* Keep the shift improvements
matouskozak added a commit to matouskozak/runtime that referenced this pull request Jul 11, 2024
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jul 23, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Light up IndexOfAnyAsciiSearcher for AVX512

3 participants

@MihaZupan@MihuBot@stephentoub
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Add Avx512 support to IndexOfAnyAsciiSearcher - #103710

Merged
MihaZupan merged 1 commit into
dotnet:mainfrom
MihaZupan:searchvalues-ascii-avx512-5
Jun 22, 2024
Merged

Add Avx512 support to IndexOfAnyAsciiSearcher#103710
MihaZupan merged 1 commit into
dotnet:mainfrom
MihaZupan:searchvalues-ascii-avx512-5

Conversation

@MihaZupan

Copy link
Copy Markdown
Member

Closes#93222

Pretty much a copy-paste of the existing Vector128/Vector256 paths (#93222 (comment)).
I had to spam a couple more AggressiveInlinings to get all the small helpers to inline even in microbenchmarks where they're never called. This is the source of slight improvements for early matches in a couple benchmarks below.

Numbers-wise it's a ~0.5 - 1 ns regression for early matches, and a speedup to ~1.5x in throughput for longer inputs.

Early matches
MethodToolchainLengthMatchAtStartMeanErrorRatio
IndexOfAny_Charmain32True4.885 ns0.0129 ns1.00
IndexOfAny_Charpr32True3.343 ns0.0007 ns0.68
IndexOfAnyExcept_Charmain32True3.056 ns0.0008 ns1.00
IndexOfAnyExcept_Charpr32True3.152 ns0.0095 ns1.03
LastIndexOfAny_Charmain32True4.166 ns0.0522 ns1.00
LastIndexOfAny_Charpr32True3.564 ns0.0748 ns0.86
LastIndexOfAnyExcept_Charmain32True3.550 ns0.0008 ns1.00
LastIndexOfAnyExcept_Charpr32True3.561 ns0.0007 ns1.00
IndexOfAny_Charmain33True3.463 ns0.0023 ns1.00
IndexOfAny_Charpr33True3.598 ns0.0037 ns1.04
IndexOfAnyExcept_Charmain33True2.834 ns0.0106 ns1.00
IndexOfAnyExcept_Charpr33True3.660 ns0.0064 ns1.29
LastIndexOfAny_Charmain33True4.158 ns0.0082 ns1.00
LastIndexOfAny_Charpr33True3.951 ns0.0004 ns0.95
LastIndexOfAnyExcept_Charmain33True3.162 ns0.0053 ns1.00
LastIndexOfAnyExcept_Charpr33True4.114 ns0.0006 ns1.30
IndexOfAny_Charmain65True3.464 ns0.0028 ns1.00
IndexOfAny_Charpr65True3.504 ns0.0768 ns1.01
IndexOfAnyExcept_Charmain65True2.833 ns0.0137 ns1.00
IndexOfAnyExcept_Charpr65True3.581 ns0.1278 ns1.26
LastIndexOfAny_Charmain65True4.128 ns0.0257 ns1.00
LastIndexOfAny_Charpr65True3.402 ns0.0005 ns0.82
LastIndexOfAnyExcept_Charmain65True3.030 ns0.0152 ns1.00
LastIndexOfAnyExcept_Charpr65True3.457 ns0.0019 ns1.14
IndexOfAny_Charmain10000True3.466 ns0.0035 ns1.00
IndexOfAny_Charpr10000True3.397 ns0.0004 ns0.98
IndexOfAnyExcept_Charmain10000True2.822 ns0.0111 ns1.00
IndexOfAnyExcept_Charpr10000True3.402 ns0.0012 ns1.20
LastIndexOfAny_Charmain10000True3.846 ns0.0118 ns1.00
LastIndexOfAny_Charpr10000True3.806 ns0.0153 ns0.99
LastIndexOfAnyExcept_Charmain10000True3.030 ns0.0044 ns1.00
LastIndexOfAnyExcept_Charpr10000True3.467 ns0.0014 ns1.14
Throughput
MethodToolchainLengthMatchAtStartMeanErrorRatio
IndexOfAny_Charmain32False3.109 ns0.0027 ns1.00
IndexOfAny_Charpr32False2.625 ns0.0006 ns0.84
IndexOfAnyExcept_Charmain32False2.460 ns0.0025 ns1.00
IndexOfAnyExcept_Charpr32False3.084 ns0.0783 ns1.25
LastIndexOfAny_Charmain32False3.063 ns0.0087 ns1.00
LastIndexOfAny_Charpr32False2.865 ns0.1573 ns0.94
LastIndexOfAnyExcept_Charmain32False3.646 ns0.4223 ns1.00
LastIndexOfAnyExcept_Charpr32False2.426 ns0.0036 ns0.68
IndexOfAny_Charmain33False4.343 ns0.0232 ns1.00
IndexOfAny_Charpr33False3.146 ns0.0026 ns0.72
IndexOfAnyExcept_Charmain33False4.320 ns0.2929 ns1.00
IndexOfAnyExcept_Charpr33False3.038 ns0.0004 ns0.71
LastIndexOfAny_Charmain33False4.913 ns0.0303 ns1.00
LastIndexOfAny_Charpr33False3.017 ns0.0008 ns0.61
LastIndexOfAnyExcept_Charmain33False3.896 ns0.0007 ns1.00
LastIndexOfAnyExcept_Charpr33False3.440 ns0.0003 ns0.88
IndexOfAny_Charmain65False5.708 ns0.0108 ns1.00
IndexOfAny_Charpr65False4.236 ns0.0008 ns0.74
IndexOfAnyExcept_Charmain65False5.004 ns0.0600 ns1.00
IndexOfAnyExcept_Charpr65False4.259 ns0.0068 ns0.85
LastIndexOfAny_Charmain65False6.250 ns0.1711 ns1.00
LastIndexOfAny_Charpr65False4.242 ns0.0043 ns0.68
LastIndexOfAnyExcept_Charmain65False6.590 ns0.7326 ns1.00
LastIndexOfAnyExcept_Charpr65False4.174 ns0.0598 ns0.65
IndexOfAny_Charmain10000False331.894 ns0.2110 ns1.00
IndexOfAny_Charpr10000False208.743 ns0.0179 ns0.63
IndexOfAnyExcept_Charmain10000False375.454 ns0.0229 ns1.00
IndexOfAnyExcept_Charpr10000False260.705 ns0.0650 ns0.69
LastIndexOfAny_Charmain10000False333.720 ns0.0841 ns1.00
LastIndexOfAny_Charpr10000False209.806 ns0.0891 ns0.63
LastIndexOfAnyExcept_Charmain10000False378.696 ns0.3796 ns1.00
LastIndexOfAnyExcept_Charpr10000False262.419 ns0.4015 ns0.69

I'll rerun the Regex benchmarks.

@MihaZupan

Copy link
Copy Markdown
MemberAuthor

@MihuBot benchmark Regex

@MihuBot

MihuBot commented Jun 20, 2024

Copy link
Copy Markdown
System.Text.RegularExpressions.Tests.Perf_Regex_Industry_RustLang_Sherlock
BenchmarkDotNet v0.13.13-nightly.20240311.145, Ubuntu 22.04.4 LTS (Jammy Jellyfish)
Intel Xeon Platinum 8370C CPU 2.80GHz, 1 CPU, 8 logical and 4 physical cores
MediumRun : .NET 9.0.0 (42.42.42.42424), X64 RyuJIT AVX-512F+CD+BW+DQ+VL+VBMI
Job=MediumRun OutlierMode=DontRemove IterationCount=15
LaunchCount=2 MemoryRandomization=True WarmupCount=10
MethodToolchainPatternMeanErrorRatioAllocatedAlloc Ratio
CountMain.*691,131.27 ns842.077 ns1.002 B1.00
CountPR.*701,291.96 ns4,208.201 ns1.012 B1.00
CountMain(?i)Holmes71,847.44 ns471.748 ns1.00-NA
CountPR(?i)Holmes72,181.78 ns346.591 ns1.00-NA
CountMain(?i)Sher[a-z]+|Hol[a-z]+102,412.23 ns2,482.554 ns1.00-NA
CountPR(?i)Sher[a-z]+|Hol[a-z]+100,226.97 ns4,693.052 ns0.98-NA
CountMain(?i)Sherlock63,157.23 ns286.797 ns1.00-NA
CountPR(?i)Sherlock63,592.22 ns294.601 ns1.013 BNA
CountMain(?i)Sherlock Holmes63,163.87 ns353.487 ns1.00-NA
CountPR(?i)Sherlock Holmes63,130.32 ns312.279 ns1.00-NA
CountMain(?i)Sherlock|Holmes|Watson96,989.85 ns3,823.367 ns1.00-NA
CountPR(?i)Sherlock|Holmes|Watson96,919.46 ns4,402.650 ns1.00-NA
CountMain(?i)Sherlock|(...)er|John|Baker [49]292,458.32 ns4,255.586 ns1.002 B1.00
CountPR(?i)Sherlock|(...)er|John|Baker [49]291,038.70 ns5,906.277 ns1.002 B1.00
CountMain(?i)the380,816.71 ns448.532 ns1.001 B1.00
CountPR(?i)the378,387.61 ns597.080 ns0.991 B1.00
CountMain(?m)^Sherlock(...)rlock Holmes$ [37]80,760.72 ns4,306.860 ns1.01-NA
CountPR(?m)^Sherlock(...)rlock Holmes$ [37]82,582.68 ns3,929.177 ns1.03-NA
CountMain(?s).*51.49 ns0.230 ns1.00-NA
CountPR(?s).*51.44 ns0.201 ns1.00-NA
CountMain[^\\n]*696,503.75 ns1,189.220 ns1.002 B1.00
CountPR[^\\n]*701,777.91 ns4,947.894 ns1.012 B1.00
CountMain[a-q][^u-z]{13}x34,252.94 ns271.978 ns1.00-NA
CountPR[a-q][^u-z]{13}x32,601.06 ns1,062.765 ns0.95-NA
CountMain[a-zA-Z]+ing4,743,957.65 ns35,002.412 ns1.0021 B1.00
CountPR[a-zA-Z]+ing4,892,478.29 ns15,606.673 ns1.0321 B1.00
CountMain\b\w+n\b9,984,392.53 ns16,833.207 ns1.0044 B1.00
CountPR\b\w+n\b10,828,533.01 ns36,736.622 ns1.0839 B0.89
CountMain\p{L}10,603,931.90 ns48,819.499 ns1.0035 B1.00
CountPR\p{L}11,179,680.36 ns9,486.172 ns1.0531 B0.89
CountMain\p{Ll}10,195,145.76 ns27,272.582 ns1.0035 B1.00
CountPR\p{Ll}11,436,304.68 ns77,659.485 ns1.1235 B1.00
CountMain\p{Lu}512,487.85 ns3,951.166 ns1.002 B1.00
CountPR\p{Lu}465,932.29 ns13,751.745 ns0.911 B0.50
CountMain\s[a-zA-Z]{0,12}ing\s5,401,364.31 ns12,575.532 ns1.0024 B1.00
CountPR\s[a-zA-Z]{0,12}ing\s5,785,507.55 ns101,020.912 ns1.0724 B1.00
CountMain\w+5,177,572.11 ns28,630.119 ns1.0018 B1.00
CountPR\w+5,505,569.07 ns66,941.247 ns1.0618 B1.00
CountMain\w+\s+Holmes4,021,934.73 ns23,376.720 ns1.0022 B1.00
CountPR\w+\s+Holmes4,287,127.11 ns34,628.196 ns1.0722 B1.00
CountMain\w+\s+Holmes\s+\w+4,157,736.06 ns3,369.514 ns1.0023 B1.00
CountPR\w+\s+Holmes\s+\w+4,448,197.47 ns8,704.825 ns1.0723 B1.00
CountMainaei60,226.44 ns177.769 ns1.00-NA
CountPRaei59,984.97 ns231.105 ns1.00-NA
CountMainaqj60,359.02 ns219.068 ns1.00-NA
CountPRaqj60,216.79 ns250.061 ns1.00-NA
CountMainHolmes70,247.90 ns381.235 ns1.00-NA
CountPRHolmes70,191.66 ns312.375 ns1.00-NA
CountMainHolmes.{0,25}(...).{0,25}Holmes [39]59,812.45 ns223.860 ns1.00-NA
CountPRHolmes.{0,25}(...).{0,25}Holmes [39]61,210.71 ns1,547.310 ns1.02-NA
CountMainSher[a-z]+|Hol[a-z]+66,397.69 ns761.073 ns1.00-NA
CountPRSher[a-z]+|Hol[a-z]+64,849.71 ns1,154.795 ns0.983 BNA
CountMainSherlock85,985.04 ns1,966.243 ns1.00-NA
CountPRSherlock83,371.97 ns3,793.039 ns0.97-NA
CountMainSherlock Holmes82,774.02 ns3,862.238 ns1.01-NA
CountPRSherlock Holmes85,172.83 ns2,128.470 ns1.03-NA
CountMainSherlock\s+Holmes83,442.70 ns3,644.738 ns1.00-NA
CountPRSherlock\s+Holmes81,539.97 ns4,064.719 ns0.98-NA
CountMainSherlock|Holmes57,513.25 ns1,431.014 ns1.00-NA
CountPRSherlock|Holmes58,628.39 ns909.981 ns1.02-NA
CountMainSherlock|Holmes|Watson81,797.43 ns3,871.627 ns1.00-NA
CountPRSherlock|Holmes|Watson77,711.13 ns263.733 ns0.95-NA
CountMainSherlock|Holm(...)er|John|Baker [45]204,100.20 ns4,644.087 ns1.001 B1.00
CountPRSherlock|Holm(...)er|John|Baker [45]209,457.96 ns1,109.672 ns1.031 B1.00
CountMainSherlock|Street34,583.11 ns1,498.786 ns1.00-NA
CountPRSherlock|Street37,804.48 ns905.387 ns1.10-NA
CountMainthe308,111.60 ns2,660.420 ns1.001 B1.00
CountPRthe304,342.71 ns867.519 ns0.991 B1.00
CountMainThe74,898.95 ns553.273 ns1.00-NA
CountPRThe74,592.77 ns544.687 ns1.00-NA
CountMainthe\s+\w+448,325.25 ns1,314.530 ns1.001 B1.00
CountPRthe\s+\w+457,653.52 ns8,459.813 ns1.021 B1.00
CountMainzqj59,408.54 ns583.905 ns1.00-NA
CountPRzqj59,892.80 ns549.900 ns1.01-NA

A few other runs

public BitVector256 Lookup = lookup;

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly Vector128<byte> Bitmap128() => Bitmap512._lower._lower;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: why a method rather than a property?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a bit more code to define the get since we need the MethodImpl on it. No other reason.

public struct AsciiState(Vector128<byte> bitmap, BitVector256 lookup)
{
public Vector256<byte> Bitmap = Vector256.Create(bitmap);
public Vector512<byte> Bitmap512 = Vector512.Create(bitmap);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These can't / shouldn't be readonly?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The TryIndexOfAny helpers (called by non-searchvalues IndexOfAny) are writing into this field directly when computing the bitmap to avoid needing an extra local.
As far as the vectorized code is concerned, these could be readonly.

@MihaZupan
MihaZupan merged commit ce1ae77 into dotnet:mainJun 22, 2024
rzikm pushed a commit to rzikm/dotnet-runtime that referenced this pull request Jun 24, 2024
MihaZupan added a commit to MihaZupan/runtime that referenced this pull request Jul 10, 2024
MihaZupan added a commit that referenced this pull request Jul 10, 2024
…4688)
* Revert "Add Avx512 support to IndexOfAnyAsciiSearcher (#103710)"
This reverts commit ce1ae77.
* Keep the test improvements
* Keep the inlining changes
* Keep the shift improvements
matouskozak added a commit to matouskozak/runtime that referenced this pull request Jul 11, 2024
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jul 23, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Light up IndexOfAnyAsciiSearcher for AVX512

3 participants

@MihaZupan@MihuBot@stephentoub
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Add Avx512 support to IndexOfAnyAsciiSearcher - #103710

Merged
MihaZupan merged 1 commit into
dotnet:mainfrom
MihaZupan:searchvalues-ascii-avx512-5
Jun 22, 2024
Merged

Add Avx512 support to IndexOfAnyAsciiSearcher#103710
MihaZupan merged 1 commit into
dotnet:mainfrom
MihaZupan:searchvalues-ascii-avx512-5

Conversation

@MihaZupan

Copy link
Copy Markdown
Member

Closes#93222

Pretty much a copy-paste of the existing Vector128/Vector256 paths (#93222 (comment)).
I had to spam a couple more AggressiveInlinings to get all the small helpers to inline even in microbenchmarks where they're never called. This is the source of slight improvements for early matches in a couple benchmarks below.

Numbers-wise it's a ~0.5 - 1 ns regression for early matches, and a speedup to ~1.5x in throughput for longer inputs.

Early matches
MethodToolchainLengthMatchAtStartMeanErrorRatio
IndexOfAny_Charmain32True4.885 ns0.0129 ns1.00
IndexOfAny_Charpr32True3.343 ns0.0007 ns0.68
IndexOfAnyExcept_Charmain32True3.056 ns0.0008 ns1.00
IndexOfAnyExcept_Charpr32True3.152 ns0.0095 ns1.03
LastIndexOfAny_Charmain32True4.166 ns0.0522 ns1.00
LastIndexOfAny_Charpr32True3.564 ns0.0748 ns0.86
LastIndexOfAnyExcept_Charmain32True3.550 ns0.0008 ns1.00
LastIndexOfAnyExcept_Charpr32True3.561 ns0.0007 ns1.00
IndexOfAny_Charmain33True3.463 ns0.0023 ns1.00
IndexOfAny_Charpr33True3.598 ns0.0037 ns1.04
IndexOfAnyExcept_Charmain33True2.834 ns0.0106 ns1.00
IndexOfAnyExcept_Charpr33True3.660 ns0.0064 ns1.29
LastIndexOfAny_Charmain33True4.158 ns0.0082 ns1.00
LastIndexOfAny_Charpr33True3.951 ns0.0004 ns0.95
LastIndexOfAnyExcept_Charmain33True3.162 ns0.0053 ns1.00
LastIndexOfAnyExcept_Charpr33True4.114 ns0.0006 ns1.30
IndexOfAny_Charmain65True3.464 ns0.0028 ns1.00
IndexOfAny_Charpr65True3.504 ns0.0768 ns1.01
IndexOfAnyExcept_Charmain65True2.833 ns0.0137 ns1.00
IndexOfAnyExcept_Charpr65True3.581 ns0.1278 ns1.26
LastIndexOfAny_Charmain65True4.128 ns0.0257 ns1.00
LastIndexOfAny_Charpr65True3.402 ns0.0005 ns0.82
LastIndexOfAnyExcept_Charmain65True3.030 ns0.0152 ns1.00
LastIndexOfAnyExcept_Charpr65True3.457 ns0.0019 ns1.14
IndexOfAny_Charmain10000True3.466 ns0.0035 ns1.00
IndexOfAny_Charpr10000True3.397 ns0.0004 ns0.98
IndexOfAnyExcept_Charmain10000True2.822 ns0.0111 ns1.00
IndexOfAnyExcept_Charpr10000True3.402 ns0.0012 ns1.20
LastIndexOfAny_Charmain10000True3.846 ns0.0118 ns1.00
LastIndexOfAny_Charpr10000True3.806 ns0.0153 ns0.99
LastIndexOfAnyExcept_Charmain10000True3.030 ns0.0044 ns1.00
LastIndexOfAnyExcept_Charpr10000True3.467 ns0.0014 ns1.14
Throughput
MethodToolchainLengthMatchAtStartMeanErrorRatio
IndexOfAny_Charmain32False3.109 ns0.0027 ns1.00
IndexOfAny_Charpr32False2.625 ns0.0006 ns0.84
IndexOfAnyExcept_Charmain32False2.460 ns0.0025 ns1.00
IndexOfAnyExcept_Charpr32False3.084 ns0.0783 ns1.25
LastIndexOfAny_Charmain32False3.063 ns0.0087 ns1.00
LastIndexOfAny_Charpr32False2.865 ns0.1573 ns0.94
LastIndexOfAnyExcept_Charmain32False3.646 ns0.4223 ns1.00
LastIndexOfAnyExcept_Charpr32False2.426 ns0.0036 ns0.68
IndexOfAny_Charmain33False4.343 ns0.0232 ns1.00
IndexOfAny_Charpr33False3.146 ns0.0026 ns0.72
IndexOfAnyExcept_Charmain33False4.320 ns0.2929 ns1.00
IndexOfAnyExcept_Charpr33False3.038 ns0.0004 ns0.71
LastIndexOfAny_Charmain33False4.913 ns0.0303 ns1.00
LastIndexOfAny_Charpr33False3.017 ns0.0008 ns0.61
LastIndexOfAnyExcept_Charmain33False3.896 ns0.0007 ns1.00
LastIndexOfAnyExcept_Charpr33False3.440 ns0.0003 ns0.88
IndexOfAny_Charmain65False5.708 ns0.0108 ns1.00
IndexOfAny_Charpr65False4.236 ns0.0008 ns0.74
IndexOfAnyExcept_Charmain65False5.004 ns0.0600 ns1.00
IndexOfAnyExcept_Charpr65False4.259 ns0.0068 ns0.85
LastIndexOfAny_Charmain65False6.250 ns0.1711 ns1.00
LastIndexOfAny_Charpr65False4.242 ns0.0043 ns0.68
LastIndexOfAnyExcept_Charmain65False6.590 ns0.7326 ns1.00
LastIndexOfAnyExcept_Charpr65False4.174 ns0.0598 ns0.65
IndexOfAny_Charmain10000False331.894 ns0.2110 ns1.00
IndexOfAny_Charpr10000False208.743 ns0.0179 ns0.63
IndexOfAnyExcept_Charmain10000False375.454 ns0.0229 ns1.00
IndexOfAnyExcept_Charpr10000False260.705 ns0.0650 ns0.69
LastIndexOfAny_Charmain10000False333.720 ns0.0841 ns1.00
LastIndexOfAny_Charpr10000False209.806 ns0.0891 ns0.63
LastIndexOfAnyExcept_Charmain10000False378.696 ns0.3796 ns1.00
LastIndexOfAnyExcept_Charpr10000False262.419 ns0.4015 ns0.69

I'll rerun the Regex benchmarks.

@MihaZupan

Copy link
Copy Markdown
MemberAuthor

@MihuBot benchmark Regex

@MihuBot

MihuBot commented Jun 20, 2024

Copy link
Copy Markdown
System.Text.RegularExpressions.Tests.Perf_Regex_Industry_RustLang_Sherlock
BenchmarkDotNet v0.13.13-nightly.20240311.145, Ubuntu 22.04.4 LTS (Jammy Jellyfish)
Intel Xeon Platinum 8370C CPU 2.80GHz, 1 CPU, 8 logical and 4 physical cores
MediumRun : .NET 9.0.0 (42.42.42.42424), X64 RyuJIT AVX-512F+CD+BW+DQ+VL+VBMI
Job=MediumRun OutlierMode=DontRemove IterationCount=15
LaunchCount=2 MemoryRandomization=True WarmupCount=10
MethodToolchainPatternMeanErrorRatioAllocatedAlloc Ratio
CountMain.*691,131.27 ns842.077 ns1.002 B1.00
CountPR.*701,291.96 ns4,208.201 ns1.012 B1.00
CountMain(?i)Holmes71,847.44 ns471.748 ns1.00-NA
CountPR(?i)Holmes72,181.78 ns346.591 ns1.00-NA
CountMain(?i)Sher[a-z]+|Hol[a-z]+102,412.23 ns2,482.554 ns1.00-NA
CountPR(?i)Sher[a-z]+|Hol[a-z]+100,226.97 ns4,693.052 ns0.98-NA
CountMain(?i)Sherlock63,157.23 ns286.797 ns1.00-NA
CountPR(?i)Sherlock63,592.22 ns294.601 ns1.013 BNA
CountMain(?i)Sherlock Holmes63,163.87 ns353.487 ns1.00-NA
CountPR(?i)Sherlock Holmes63,130.32 ns312.279 ns1.00-NA
CountMain(?i)Sherlock|Holmes|Watson96,989.85 ns3,823.367 ns1.00-NA
CountPR(?i)Sherlock|Holmes|Watson96,919.46 ns4,402.650 ns1.00-NA
CountMain(?i)Sherlock|(...)er|John|Baker [49]292,458.32 ns4,255.586 ns1.002 B1.00
CountPR(?i)Sherlock|(...)er|John|Baker [49]291,038.70 ns5,906.277 ns1.002 B1.00
CountMain(?i)the380,816.71 ns448.532 ns1.001 B1.00
CountPR(?i)the378,387.61 ns597.080 ns0.991 B1.00
CountMain(?m)^Sherlock(...)rlock Holmes$ [37]80,760.72 ns4,306.860 ns1.01-NA
CountPR(?m)^Sherlock(...)rlock Holmes$ [37]82,582.68 ns3,929.177 ns1.03-NA
CountMain(?s).*51.49 ns0.230 ns1.00-NA
CountPR(?s).*51.44 ns0.201 ns1.00-NA
CountMain[^\\n]*696,503.75 ns1,189.220 ns1.002 B1.00
CountPR[^\\n]*701,777.91 ns4,947.894 ns1.012 B1.00
CountMain[a-q][^u-z]{13}x34,252.94 ns271.978 ns1.00-NA
CountPR[a-q][^u-z]{13}x32,601.06 ns1,062.765 ns0.95-NA
CountMain[a-zA-Z]+ing4,743,957.65 ns35,002.412 ns1.0021 B1.00
CountPR[a-zA-Z]+ing4,892,478.29 ns15,606.673 ns1.0321 B1.00
CountMain\b\w+n\b9,984,392.53 ns16,833.207 ns1.0044 B1.00
CountPR\b\w+n\b10,828,533.01 ns36,736.622 ns1.0839 B0.89
CountMain\p{L}10,603,931.90 ns48,819.499 ns1.0035 B1.00
CountPR\p{L}11,179,680.36 ns9,486.172 ns1.0531 B0.89
CountMain\p{Ll}10,195,145.76 ns27,272.582 ns1.0035 B1.00
CountPR\p{Ll}11,436,304.68 ns77,659.485 ns1.1235 B1.00
CountMain\p{Lu}512,487.85 ns3,951.166 ns1.002 B1.00
CountPR\p{Lu}465,932.29 ns13,751.745 ns0.911 B0.50
CountMain\s[a-zA-Z]{0,12}ing\s5,401,364.31 ns12,575.532 ns1.0024 B1.00
CountPR\s[a-zA-Z]{0,12}ing\s5,785,507.55 ns101,020.912 ns1.0724 B1.00
CountMain\w+5,177,572.11 ns28,630.119 ns1.0018 B1.00
CountPR\w+5,505,569.07 ns66,941.247 ns1.0618 B1.00
CountMain\w+\s+Holmes4,021,934.73 ns23,376.720 ns1.0022 B1.00
CountPR\w+\s+Holmes4,287,127.11 ns34,628.196 ns1.0722 B1.00
CountMain\w+\s+Holmes\s+\w+4,157,736.06 ns3,369.514 ns1.0023 B1.00
CountPR\w+\s+Holmes\s+\w+4,448,197.47 ns8,704.825 ns1.0723 B1.00
CountMainaei60,226.44 ns177.769 ns1.00-NA
CountPRaei59,984.97 ns231.105 ns1.00-NA
CountMainaqj60,359.02 ns219.068 ns1.00-NA
CountPRaqj60,216.79 ns250.061 ns1.00-NA
CountMainHolmes70,247.90 ns381.235 ns1.00-NA
CountPRHolmes70,191.66 ns312.375 ns1.00-NA
CountMainHolmes.{0,25}(...).{0,25}Holmes [39]59,812.45 ns223.860 ns1.00-NA
CountPRHolmes.{0,25}(...).{0,25}Holmes [39]61,210.71 ns1,547.310 ns1.02-NA
CountMainSher[a-z]+|Hol[a-z]+66,397.69 ns761.073 ns1.00-NA
CountPRSher[a-z]+|Hol[a-z]+64,849.71 ns1,154.795 ns0.983 BNA
CountMainSherlock85,985.04 ns1,966.243 ns1.00-NA
CountPRSherlock83,371.97 ns3,793.039 ns0.97-NA
CountMainSherlock Holmes82,774.02 ns3,862.238 ns1.01-NA
CountPRSherlock Holmes85,172.83 ns2,128.470 ns1.03-NA
CountMainSherlock\s+Holmes83,442.70 ns3,644.738 ns1.00-NA
CountPRSherlock\s+Holmes81,539.97 ns4,064.719 ns0.98-NA
CountMainSherlock|Holmes57,513.25 ns1,431.014 ns1.00-NA
CountPRSherlock|Holmes58,628.39 ns909.981 ns1.02-NA
CountMainSherlock|Holmes|Watson81,797.43 ns3,871.627 ns1.00-NA
CountPRSherlock|Holmes|Watson77,711.13 ns263.733 ns0.95-NA
CountMainSherlock|Holm(...)er|John|Baker [45]204,100.20 ns4,644.087 ns1.001 B1.00
CountPRSherlock|Holm(...)er|John|Baker [45]209,457.96 ns1,109.672 ns1.031 B1.00
CountMainSherlock|Street34,583.11 ns1,498.786 ns1.00-NA
CountPRSherlock|Street37,804.48 ns905.387 ns1.10-NA
CountMainthe308,111.60 ns2,660.420 ns1.001 B1.00
CountPRthe304,342.71 ns867.519 ns0.991 B1.00
CountMainThe74,898.95 ns553.273 ns1.00-NA
CountPRThe74,592.77 ns544.687 ns1.00-NA
CountMainthe\s+\w+448,325.25 ns1,314.530 ns1.001 B1.00
CountPRthe\s+\w+457,653.52 ns8,459.813 ns1.021 B1.00
CountMainzqj59,408.54 ns583.905 ns1.00-NA
CountPRzqj59,892.80 ns549.900 ns1.01-NA

A few other runs

public BitVector256 Lookup = lookup;

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly Vector128<byte> Bitmap128() => Bitmap512._lower._lower;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: why a method rather than a property?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a bit more code to define the get since we need the MethodImpl on it. No other reason.

public struct AsciiState(Vector128<byte> bitmap, BitVector256 lookup)
{
public Vector256<byte> Bitmap = Vector256.Create(bitmap);
public Vector512<byte> Bitmap512 = Vector512.Create(bitmap);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These can't / shouldn't be readonly?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The TryIndexOfAny helpers (called by non-searchvalues IndexOfAny) are writing into this field directly when computing the bitmap to avoid needing an extra local.
As far as the vectorized code is concerned, these could be readonly.

@MihaZupan
MihaZupan merged commit ce1ae77 into dotnet:mainJun 22, 2024
rzikm pushed a commit to rzikm/dotnet-runtime that referenced this pull request Jun 24, 2024
MihaZupan added a commit to MihaZupan/runtime that referenced this pull request Jul 10, 2024
MihaZupan added a commit that referenced this pull request Jul 10, 2024
…4688)
* Revert "Add Avx512 support to IndexOfAnyAsciiSearcher (#103710)"
This reverts commit ce1ae77.
* Keep the test improvements
* Keep the inlining changes
* Keep the shift improvements
matouskozak added a commit to matouskozak/runtime that referenced this pull request Jul 11, 2024
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jul 23, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Light up IndexOfAnyAsciiSearcher for AVX512

3 participants

@MihaZupan@MihuBot@stephentoub
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Add Avx512 support to IndexOfAnyAsciiSearcher - #103710

Merged
MihaZupan merged 1 commit into
dotnet:mainfrom
MihaZupan:searchvalues-ascii-avx512-5
Jun 22, 2024
Merged

Add Avx512 support to IndexOfAnyAsciiSearcher#103710
MihaZupan merged 1 commit into
dotnet:mainfrom
MihaZupan:searchvalues-ascii-avx512-5

Conversation

@MihaZupan

Copy link
Copy Markdown
Member

Closes#93222

Pretty much a copy-paste of the existing Vector128/Vector256 paths (#93222 (comment)).
I had to spam a couple more AggressiveInlinings to get all the small helpers to inline even in microbenchmarks where they're never called. This is the source of slight improvements for early matches in a couple benchmarks below.

Numbers-wise it's a ~0.5 - 1 ns regression for early matches, and a speedup to ~1.5x in throughput for longer inputs.

Early matches
MethodToolchainLengthMatchAtStartMeanErrorRatio
IndexOfAny_Charmain32True4.885 ns0.0129 ns1.00
IndexOfAny_Charpr32True3.343 ns0.0007 ns0.68
IndexOfAnyExcept_Charmain32True3.056 ns0.0008 ns1.00
IndexOfAnyExcept_Charpr32True3.152 ns0.0095 ns1.03
LastIndexOfAny_Charmain32True4.166 ns0.0522 ns1.00
LastIndexOfAny_Charpr32True3.564 ns0.0748 ns0.86
LastIndexOfAnyExcept_Charmain32True3.550 ns0.0008 ns1.00
LastIndexOfAnyExcept_Charpr32True3.561 ns0.0007 ns1.00
IndexOfAny_Charmain33True3.463 ns0.0023 ns1.00
IndexOfAny_Charpr33True3.598 ns0.0037 ns1.04
IndexOfAnyExcept_Charmain33True2.834 ns0.0106 ns1.00
IndexOfAnyExcept_Charpr33True3.660 ns0.0064 ns1.29
LastIndexOfAny_Charmain33True4.158 ns0.0082 ns1.00
LastIndexOfAny_Charpr33True3.951 ns0.0004 ns0.95
LastIndexOfAnyExcept_Charmain33True3.162 ns0.0053 ns1.00
LastIndexOfAnyExcept_Charpr33True4.114 ns0.0006 ns1.30
IndexOfAny_Charmain65True3.464 ns0.0028 ns1.00
IndexOfAny_Charpr65True3.504 ns0.0768 ns1.01
IndexOfAnyExcept_Charmain65True2.833 ns0.0137 ns1.00
IndexOfAnyExcept_Charpr65True3.581 ns0.1278 ns1.26
LastIndexOfAny_Charmain65True4.128 ns0.0257 ns1.00
LastIndexOfAny_Charpr65True3.402 ns0.0005 ns0.82
LastIndexOfAnyExcept_Charmain65True3.030 ns0.0152 ns1.00
LastIndexOfAnyExcept_Charpr65True3.457 ns0.0019 ns1.14
IndexOfAny_Charmain10000True3.466 ns0.0035 ns1.00
IndexOfAny_Charpr10000True3.397 ns0.0004 ns0.98
IndexOfAnyExcept_Charmain10000True2.822 ns0.0111 ns1.00
IndexOfAnyExcept_Charpr10000True3.402 ns0.0012 ns1.20
LastIndexOfAny_Charmain10000True3.846 ns0.0118 ns1.00
LastIndexOfAny_Charpr10000True3.806 ns0.0153 ns0.99
LastIndexOfAnyExcept_Charmain10000True3.030 ns0.0044 ns1.00
LastIndexOfAnyExcept_Charpr10000True3.467 ns0.0014 ns1.14
Throughput
MethodToolchainLengthMatchAtStartMeanErrorRatio
IndexOfAny_Charmain32False3.109 ns0.0027 ns1.00
IndexOfAny_Charpr32False2.625 ns0.0006 ns0.84
IndexOfAnyExcept_Charmain32False2.460 ns0.0025 ns1.00
IndexOfAnyExcept_Charpr32False3.084 ns0.0783 ns1.25
LastIndexOfAny_Charmain32False3.063 ns0.0087 ns1.00
LastIndexOfAny_Charpr32False2.865 ns0.1573 ns0.94
LastIndexOfAnyExcept_Charmain32False3.646 ns0.4223 ns1.00
LastIndexOfAnyExcept_Charpr32False2.426 ns0.0036 ns0.68
IndexOfAny_Charmain33False4.343 ns0.0232 ns1.00
IndexOfAny_Charpr33False3.146 ns0.0026 ns0.72
IndexOfAnyExcept_Charmain33False4.320 ns0.2929 ns1.00
IndexOfAnyExcept_Charpr33False3.038 ns0.0004 ns0.71
LastIndexOfAny_Charmain33False4.913 ns0.0303 ns1.00
LastIndexOfAny_Charpr33False3.017 ns0.0008 ns0.61
LastIndexOfAnyExcept_Charmain33False3.896 ns0.0007 ns1.00
LastIndexOfAnyExcept_Charpr33False3.440 ns0.0003 ns0.88
IndexOfAny_Charmain65False5.708 ns0.0108 ns1.00
IndexOfAny_Charpr65False4.236 ns0.0008 ns0.74
IndexOfAnyExcept_Charmain65False5.004 ns0.0600 ns1.00
IndexOfAnyExcept_Charpr65False4.259 ns0.0068 ns0.85
LastIndexOfAny_Charmain65False6.250 ns0.1711 ns1.00
LastIndexOfAny_Charpr65False4.242 ns0.0043 ns0.68
LastIndexOfAnyExcept_Charmain65False6.590 ns0.7326 ns1.00
LastIndexOfAnyExcept_Charpr65False4.174 ns0.0598 ns0.65
IndexOfAny_Charmain10000False331.894 ns0.2110 ns1.00
IndexOfAny_Charpr10000False208.743 ns0.0179 ns0.63
IndexOfAnyExcept_Charmain10000False375.454 ns0.0229 ns1.00
IndexOfAnyExcept_Charpr10000False260.705 ns0.0650 ns0.69
LastIndexOfAny_Charmain10000False333.720 ns0.0841 ns1.00
LastIndexOfAny_Charpr10000False209.806 ns0.0891 ns0.63
LastIndexOfAnyExcept_Charmain10000False378.696 ns0.3796 ns1.00
LastIndexOfAnyExcept_Charpr10000False262.419 ns0.4015 ns0.69

I'll rerun the Regex benchmarks.

@MihaZupan

Copy link
Copy Markdown
MemberAuthor

@MihuBot benchmark Regex

@MihuBot

MihuBot commented Jun 20, 2024

Copy link
Copy Markdown
System.Text.RegularExpressions.Tests.Perf_Regex_Industry_RustLang_Sherlock
BenchmarkDotNet v0.13.13-nightly.20240311.145, Ubuntu 22.04.4 LTS (Jammy Jellyfish)
Intel Xeon Platinum 8370C CPU 2.80GHz, 1 CPU, 8 logical and 4 physical cores
MediumRun : .NET 9.0.0 (42.42.42.42424), X64 RyuJIT AVX-512F+CD+BW+DQ+VL+VBMI
Job=MediumRun OutlierMode=DontRemove IterationCount=15
LaunchCount=2 MemoryRandomization=True WarmupCount=10
MethodToolchainPatternMeanErrorRatioAllocatedAlloc Ratio
CountMain.*691,131.27 ns842.077 ns1.002 B1.00
CountPR.*701,291.96 ns4,208.201 ns1.012 B1.00
CountMain(?i)Holmes71,847.44 ns471.748 ns1.00-NA
CountPR(?i)Holmes72,181.78 ns346.591 ns1.00-NA
CountMain(?i)Sher[a-z]+|Hol[a-z]+102,412.23 ns2,482.554 ns1.00-NA
CountPR(?i)Sher[a-z]+|Hol[a-z]+100,226.97 ns4,693.052 ns0.98-NA
CountMain(?i)Sherlock63,157.23 ns286.797 ns1.00-NA
CountPR(?i)Sherlock63,592.22 ns294.601 ns1.013 BNA
CountMain(?i)Sherlock Holmes63,163.87 ns353.487 ns1.00-NA
CountPR(?i)Sherlock Holmes63,130.32 ns312.279 ns1.00-NA
CountMain(?i)Sherlock|Holmes|Watson96,989.85 ns3,823.367 ns1.00-NA
CountPR(?i)Sherlock|Holmes|Watson96,919.46 ns4,402.650 ns1.00-NA
CountMain(?i)Sherlock|(...)er|John|Baker [49]292,458.32 ns4,255.586 ns1.002 B1.00
CountPR(?i)Sherlock|(...)er|John|Baker [49]291,038.70 ns5,906.277 ns1.002 B1.00
CountMain(?i)the380,816.71 ns448.532 ns1.001 B1.00
CountPR(?i)the378,387.61 ns597.080 ns0.991 B1.00
CountMain(?m)^Sherlock(...)rlock Holmes$ [37]80,760.72 ns4,306.860 ns1.01-NA
CountPR(?m)^Sherlock(...)rlock Holmes$ [37]82,582.68 ns3,929.177 ns1.03-NA
CountMain(?s).*51.49 ns0.230 ns1.00-NA
CountPR(?s).*51.44 ns0.201 ns1.00-NA
CountMain[^\\n]*696,503.75 ns1,189.220 ns1.002 B1.00
CountPR[^\\n]*701,777.91 ns4,947.894 ns1.012 B1.00
CountMain[a-q][^u-z]{13}x34,252.94 ns271.978 ns1.00-NA
CountPR[a-q][^u-z]{13}x32,601.06 ns1,062.765 ns0.95-NA
CountMain[a-zA-Z]+ing4,743,957.65 ns35,002.412 ns1.0021 B1.00
CountPR[a-zA-Z]+ing4,892,478.29 ns15,606.673 ns1.0321 B1.00
CountMain\b\w+n\b9,984,392.53 ns16,833.207 ns1.0044 B1.00
CountPR\b\w+n\b10,828,533.01 ns36,736.622 ns1.0839 B0.89
CountMain\p{L}10,603,931.90 ns48,819.499 ns1.0035 B1.00
CountPR\p{L}11,179,680.36 ns9,486.172 ns1.0531 B0.89
CountMain\p{Ll}10,195,145.76 ns27,272.582 ns1.0035 B1.00
CountPR\p{Ll}11,436,304.68 ns77,659.485 ns1.1235 B1.00
CountMain\p{Lu}512,487.85 ns3,951.166 ns1.002 B1.00
CountPR\p{Lu}465,932.29 ns13,751.745 ns0.911 B0.50
CountMain\s[a-zA-Z]{0,12}ing\s5,401,364.31 ns12,575.532 ns1.0024 B1.00
CountPR\s[a-zA-Z]{0,12}ing\s5,785,507.55 ns101,020.912 ns1.0724 B1.00
CountMain\w+5,177,572.11 ns28,630.119 ns1.0018 B1.00
CountPR\w+5,505,569.07 ns66,941.247 ns1.0618 B1.00
CountMain\w+\s+Holmes4,021,934.73 ns23,376.720 ns1.0022 B1.00
CountPR\w+\s+Holmes4,287,127.11 ns34,628.196 ns1.0722 B1.00
CountMain\w+\s+Holmes\s+\w+4,157,736.06 ns3,369.514 ns1.0023 B1.00
CountPR\w+\s+Holmes\s+\w+4,448,197.47 ns8,704.825 ns1.0723 B1.00
CountMainaei60,226.44 ns177.769 ns1.00-NA
CountPRaei59,984.97 ns231.105 ns1.00-NA
CountMainaqj60,359.02 ns219.068 ns1.00-NA
CountPRaqj60,216.79 ns250.061 ns1.00-NA
CountMainHolmes70,247.90 ns381.235 ns1.00-NA
CountPRHolmes70,191.66 ns312.375 ns1.00-NA
CountMainHolmes.{0,25}(...).{0,25}Holmes [39]59,812.45 ns223.860 ns1.00-NA
CountPRHolmes.{0,25}(...).{0,25}Holmes [39]61,210.71 ns1,547.310 ns1.02-NA
CountMainSher[a-z]+|Hol[a-z]+66,397.69 ns761.073 ns1.00-NA
CountPRSher[a-z]+|Hol[a-z]+64,849.71 ns1,154.795 ns0.983 BNA
CountMainSherlock85,985.04 ns1,966.243 ns1.00-NA
CountPRSherlock83,371.97 ns3,793.039 ns0.97-NA
CountMainSherlock Holmes82,774.02 ns3,862.238 ns1.01-NA
CountPRSherlock Holmes85,172.83 ns2,128.470 ns1.03-NA
CountMainSherlock\s+Holmes83,442.70 ns3,644.738 ns1.00-NA
CountPRSherlock\s+Holmes81,539.97 ns4,064.719 ns0.98-NA
CountMainSherlock|Holmes57,513.25 ns1,431.014 ns1.00-NA
CountPRSherlock|Holmes58,628.39 ns909.981 ns1.02-NA
CountMainSherlock|Holmes|Watson81,797.43 ns3,871.627 ns1.00-NA
CountPRSherlock|Holmes|Watson77,711.13 ns263.733 ns0.95-NA
CountMainSherlock|Holm(...)er|John|Baker [45]204,100.20 ns4,644.087 ns1.001 B1.00
CountPRSherlock|Holm(...)er|John|Baker [45]209,457.96 ns1,109.672 ns1.031 B1.00
CountMainSherlock|Street34,583.11 ns1,498.786 ns1.00-NA
CountPRSherlock|Street37,804.48 ns905.387 ns1.10-NA
CountMainthe308,111.60 ns2,660.420 ns1.001 B1.00
CountPRthe304,342.71 ns867.519 ns0.991 B1.00
CountMainThe74,898.95 ns553.273 ns1.00-NA
CountPRThe74,592.77 ns544.687 ns1.00-NA
CountMainthe\s+\w+448,325.25 ns1,314.530 ns1.001 B1.00
CountPRthe\s+\w+457,653.52 ns8,459.813 ns1.021 B1.00
CountMainzqj59,408.54 ns583.905 ns1.00-NA
CountPRzqj59,892.80 ns549.900 ns1.01-NA

A few other runs

public BitVector256 Lookup = lookup;

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public readonly Vector128<byte> Bitmap128() => Bitmap512._lower._lower;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: why a method rather than a property?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a bit more code to define the get since we need the MethodImpl on it. No other reason.

public struct AsciiState(Vector128<byte> bitmap, BitVector256 lookup)
{
public Vector256<byte> Bitmap = Vector256.Create(bitmap);
public Vector512<byte> Bitmap512 = Vector512.Create(bitmap);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These can't / shouldn't be readonly?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The TryIndexOfAny helpers (called by non-searchvalues IndexOfAny) are writing into this field directly when computing the bitmap to avoid needing an extra local.
As far as the vectorized code is concerned, these could be readonly.

@MihaZupan
MihaZupan merged commit ce1ae77 into dotnet:mainJun 22, 2024
rzikm pushed a commit to rzikm/dotnet-runtime that referenced this pull request Jun 24, 2024
MihaZupan added a commit to MihaZupan/runtime that referenced this pull request Jul 10, 2024
MihaZupan added a commit that referenced this pull request Jul 10, 2024
…4688)
* Revert "Add Avx512 support to IndexOfAnyAsciiSearcher (#103710)"
This reverts commit ce1ae77.
* Keep the test improvements
* Keep the inlining changes
* Keep the shift improvements
matouskozak added a commit to matouskozak/runtime that referenced this pull request Jul 11, 2024
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jul 23, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Light up IndexOfAnyAsciiSearcher for AVX512

3 participants

@MihaZupan@MihuBot@stephentoub