') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); Vectorize ProbabilisticMap.IndexOfAny by MihaZupan · Pull Request #80963 · dotnet/runtime · GitHub
Skip to content

Vectorize ProbabilisticMap.IndexOfAny - #80963

Merged
stephentoub merged 9 commits into
dotnet:mainfrom
MihaZupan:avx2-probabilisticmap
Mar 10, 2023
Merged

Vectorize ProbabilisticMap.IndexOfAny#80963
stephentoub merged 9 commits into
dotnet:mainfrom
MihaZupan:avx2-probabilisticmap

Conversation

@MihaZupan

@MihaZupanMihaZupan commented Jan 21, 2023

Copy link
Copy Markdown
Member

AVX2

MethodToolchainNewLineFrequencyLengthMeanErrorRatio
ReplaceLineEndingsmain01000011.481 us0.0569 us1.00
ReplaceLineEndingspr0100001.086 us0.0026 us0.09
ReplaceLineEndingsmain0.051000024.280 us0.0478 us1.00
ReplaceLineEndingspr0.051000013.983 us0.0596 us0.58
ReplaceLineEndingsmain0.11000035.616 us0.1959 us1.00
ReplaceLineEndingspr0.11000027.322 us0.3056 us0.77
ReplaceLineEndingsmain0.21000058.372 us1.0346 us1.00
ReplaceLineEndingspr0.21000052.060 us0.2331 us0.89
ReplaceLineEndingsmain110000160.760 us1.1764 us1.00
ReplaceLineEndingspr110000201.541 us4.8189 us1.26

ARM64

MethodLengthMeanError
Old1000013.122 µs0.0117 µs
New100003.701 µs0.0012 µs
Benchmark source
publicclassReplaceLineEndingsBenchmark{privatestring_input;[Params(0.0,0.05,0.1,0.2,1.0)]publicdoubleNewLineFrequency;[Params(10_000)]publicintLength;[GlobalSetup]publicvoidSetup(){char[]input=newchar[Length];varrng=newRandom(42);for(inti=0;i<input.Length;i++){if(rng.NextDouble()<NewLineFrequency){input[i]='\n';}else{charc;do{c=(char)rng.Next(0,65536);}while("\r\n\f\u0085\u2028\u2029".Contains(c));input[i]=c;}}_input=newstring(input);}[Benchmark]publicstringReplaceLineEndings()=>_input.ReplaceLineEndings();}

If we care, we could also do this for LastIndexOfAny.

#80297 could be interesting for ARM if we could do a 256-bit lookup instead of blending together smaller lookups.

@MihaZupanMihaZupan added this to the 8.0.0 milestone Jan 21, 2023
@MihaZupanMihaZupan self-assigned this Jan 21, 2023
@ghost

Copy link
Copy Markdown

Tagging subscribers to this area: @dotnet/area-system-memory
See info in area-owners.md if you want to be subscribed.

Issue Details
MethodToolchainNewLineFrequencyLengthMeanErrorRatio
ReplaceLineEndingsmain01000011,172.53 ns18.391 ns1.00
ReplaceLineEndingspr0100002,420.99 ns5.713 ns0.22
ReplaceLineEndingsmain0.051000024,471.23 ns167.827 ns1.00
ReplaceLineEndingspr0.051000015,055.74 ns116.653 ns0.62
ReplaceLineEndingsmain0.11000037,305.05 ns724.469 ns1.00
ReplaceLineEndingspr0.11000027,831.78 ns862.877 ns0.75
ReplaceLineEndingsmain0.21000057,099.06 ns305.187 ns1.00
ReplaceLineEndingspr0.21000047,964.65 ns562.536 ns0.84
ReplaceLineEndingsmain110000160,707.06 ns1,484.932 ns1.00
ReplaceLineEndingspr110000175,589.93 ns3,588.352 ns1.09
Benchmark source
publicclassReplaceLineEndingsBenchmark{privatestring_input;[Params(0.0,0.05,0.1,0.2,1.0)]publicdoubleNewLineFrequency;[Params(10_000)]publicintLength;[GlobalSetup]publicvoidSetup(){char[]input=newchar[Length];varrng=newRandom(42);for(inti=0;i<input.Length;i++){if(rng.NextDouble()<NewLineFrequency){input[i]='\n';}else{charc;do{c=(char)rng.Next(0,65536);}while("\r\n\f\u0085\u2028\u2029".Contains(c));input[i]=c;}}_input=newstring(input);}[Benchmark]publicstringReplaceLineEndings()=>_input.ReplaceLineEndings();}

If we care, we could also do this for LastIndexOfAny.

I don't know if it's possible to do something similar efficiently on ARM given that the bloom filter in this case is 256-bit.
We could experiment with different implementations that would vectorize well with Vector128.

Author:MihaZupan
Assignees:MihaZupan
Labels:

area-System.Memory

Milestone:8.0.0

@MihaZupan
MihaZupan marked this pull request as draft January 21, 2023 05:59
@MihaZupanMihaZupan changed the title Vectorize ProbabilisticMap.IndexOfAny on AVX2Vectorize ProbabilisticMap.IndexOfAnyJan 21, 2023
@MihaZupan
MihaZupan marked this pull request as ready for review January 21, 2023 09:37
@MihaZupan

Copy link
Copy Markdown
MemberAuthor

/azp run runtime-libraries-coreclr outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@MihaZupan

MihaZupan commented Jan 26, 2023

Copy link
Copy Markdown
MemberAuthor

Added Vector{128/256}.LoadUnsafe(ref char) and Vector128.ShuffleUnsafe as internal APIs for now and replaced a few existing uses.

Comment threadsrc/libraries/System.Private.CoreLib/src/System/Guid.cs Outdated
@lewing

Copy link
Copy Markdown
Member

@radekdoulik we should add PackedSimd versions of the Unsafe* functions wasm supports to ease handling all the calling callers. I'm not sure we have a great pattern to simplify the *.IsHardwareAccelerated paths that works for all the cases yet but that is worth considering too.

@MihaZupan

Copy link
Copy Markdown
MemberAuthor

Any thoughts on this @dotnet/area-system-memory?

@tannergooding
tannergooding self-requested a review February 22, 2023 21:21
Comment on lines 167 to 169

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 are different because shifting via byte isn't accelerated on xarch, right?

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.

Yes. We do the same thing in IndexOfAnyAsciiSearcher as well, where that also feeds into a shuffle

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.

👍, probably worth opening an issue so an efficient implementation can be done and we can avoid the separate paths here.

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.

@MihaZupan

Copy link
Copy Markdown
MemberAuthor

Failures are: #82575, #81123, #82611

@MihaZupan

Copy link
Copy Markdown
MemberAuthor

Anything else that should be changed here, or is this one good to merge @tannergooding?

@MihaZupan

Copy link
Copy Markdown
MemberAuthor

@tannergooding can this be merged? (I'm trying to avoid more merge conflicts as this was already rebased a fair number of times)

@tannergooding

Copy link
Copy Markdown
Member

Another merge conflict popped up.

Would be good to see some more benchmark numbers to better display where the cutoff is for the index ratio.

Likely also needs a secondary review from someone like @stephentoub given the code its touching.

@stephentoub

Copy link
Copy Markdown
Member

Thanks!

@stephentoub
stephentoub merged commit 7a0b0e1 into dotnet:mainMar 10, 2023
@ghostghost locked as resolved and limited conversation to collaborators Apr 9, 2023
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.

6 participants

@MihaZupan@lewing@tannergooding@stephentoub@EgorBo@gfoidl