Adding AVX512 path to Base64 encoding/Decoding - #92241

Merged
tannergooding merged 5 commits into
dotnet:mainfrom
DeepakRajendrakumaran:encoding
Oct 25, 2023
Merged

Adding AVX512 path to Base64 encoding/Decoding#92241
tannergooding merged 5 commits into
dotnet:mainfrom
DeepakRajendrakumaran:encoding

Conversation

@DeepakRajendrakumaran

Copy link
Copy Markdown
Contributor

Overview

This PR implements an AVX512 code path for Base64 encoding/Decoding. This is based on the work by Wojciech Muła and Daniel Lemire. There is a fast AVX512VBMI path and the fallback uses AVX512F/BW - I'll refer to these as VBMI_AVAILABLE and VBMI_UNAVAILABLE here on. For performance purposes, this will be compared to an AVX2 implementation which will be referred to as BASE_Version
Reference for the algorithm:

This version uses intrinsics directly and not generic vector libraries due to lack of current support in JIt/Vector libraries to produce optimal code. Some additional support which would be required in order to use generic vector library for implementing this would be

  1. Add ShuffleUnsafe for Vector512
  2. Extend Vector512.Shuffle() to lower to intrinsics instead of going to fallback for more cases.
  3. Expand Vector512 surface area to incorporate more high level functions

Even the current implementation can be further optimized by adding the multishift() implementation. This is a further optimization

Generated code

(Will be focusing on the actual encoding/decoding code within the loop only)

Encoding

VBMI_AVAILABLE

image

VBMI_UNAVAILABLE

image

BASE_VERSION
image

Decoding

VBMI_AVAILABLE

image

VBMI_UNAVAILABLE

image

BASE_VERSION
image

Performance

ON ICX -

BASE_VERSION vs VBMI_UNAVAILABLE

image

BASE_VERSION vs VBMI_AVAILABLE
image

@ghostghost added needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners community-contribution Indicates that the PR has been added by a community member labels Sep 18, 2023
@DeepakRajendrakumaran

Copy link
Copy Markdown
ContributorAuthor

@BruceForstall@tannergooding @dotnet/avx512-contrib

@danmoseley

Copy link
Copy Markdown
Contributor

Do we need a new entry in the third party notices file?

@EgorBo

Copy link
Copy Markdown
Member

Do we need a new entry in the third party notices file?

We should already have them if I am not mistaken (unless avx512 uses a different article)

@DeepakRajendrakumaran

Copy link
Copy Markdown
ContributorAuthor

Do we need a new entry in the third party notices file?

We should already have them if I am not mistaken (unless avx512 uses a different article)

I'm not sure about this-

The original sse and avx implementations use a similar algorithm and this is the reference provided - https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Base64Encoder.cs#L13-L14.

This implementation(the VBMI version) uses a modified version based on this(https://github.com/dotnet/runtime/pull/92241/files#diff-db463201901c2d83d2b563871ae11fafee9d5afe94e4d014b77212996b25f770R635) - https://arxiv.org/pdf/1910.05109.pdf

There is an AVX512 based implementation in there - https://github.com/aklomp/base64/tree/master/lib/arch/avx512. But it has only the encode and it requires 'multishift' which we do not currently support

@danmoseley

Copy link
Copy Markdown
Contributor

We generally acknowledge significant reuse in the TPN file even if there's a link from the sources. I see

License notice for vectorized base64 encoding / decoding
but I'm not sure it points to that pdf (eg it doesn't include Lemire in the list)

but, whatever @EgorBo recommends..

@EgorBo

Copy link
Copy Markdown
Member

I am not an expert in THIRD-PARTY-NOTICES.TXT 🙂 but seems like the link to that article is worth adding here https://github.com/dotnet/runtime/blob/main/THIRD-PARTY-NOTICES.TXT#L345

There is an AVX512 based implementation in there - https://github.com/aklomp/base64/tree/master/lib/arch/avx512.

Do we use any of the code from that repo? I see it has BSD-2 license

@DeepakRajendrakumaran

Copy link
Copy Markdown
ContributorAuthor

I am not an expert in THIRD-PARTY-NOTICES.TXT 🙂 but seems like the link to that article is worth adding here https://github.com/dotnet/runtime/blob/main/THIRD-PARTY-NOTICES.TXT#L345

There is an AVX512 based implementation in there - https://github.com/aklomp/base64/tree/master/lib/arch/avx512.

Do we use any of the code from that repo? I see it has BSD-2 license

Not directly but the logic(including shuffle constants are similar). But this implementation uses '_mm512_multishift_epi64_epi8' and that's not the one I'm using. This(https://github.com/WojciechMula/base64simd/blob/master/encode/encode.avx512vbmi.cpp) in particular is probably worth mentioning in hindsight(Since I used the non multishift version in my implementation with VBMI)

I used the below as resources to understand available implementations and available options(But they are all related). Which brings up the question which of these exactly I should be referencing

esp this for understanding : http://0x80.pl/notesen/2016-04-03-avx512-base64.html#id29

https://github.com/WojciechMula/base64simd/tree/master
https://arxiv.org/pdf/1910.05109.pdf
https://github.com/lemire/fastbase64/blob/master/src/fastavx512bwbase64.c
https://github.com/aklomp/base64/tree/master/lib/arch/avx512

@ghost

Copy link
Copy Markdown

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

Issue Details

Overview

This PR implements an AVX512 code path for Base64 encoding/Decoding. This is based on the work by Wojciech Muła and Daniel Lemire. There is a fast AVX512VBMI path and the fallback uses AVX512F/BW - I'll refer to these as VBMI_AVAILABLE and VBMI_UNAVAILABLE here on. For performance purposes, this will be compared to an AVX2 implementation which will be referred to as BASE_Version
Reference for the algorithm:

This version uses intrinsics directly and not generic vector libraries due to lack of current support in JIt/Vector libraries to produce optimal code. Some additional support which would be required in order to use generic vector library for implementing this would be

  1. Add ShuffleUnsafe for Vector512
  2. Extend Vector512.Shuffle() to lower to intrinsics instead of going to fallback for more cases.
  3. Expand Vector512 surface area to incorporate more high level functions

Even the current implementation can be further optimized by adding the multishift() implementation. This is a further optimization

Generated code

(Will be focusing on the actual encoding/decoding code within the loop only)

Encoding

VBMI_AVAILABLE

image

VBMI_UNAVAILABLE

image

BASE_VERSION
image

Decoding

VBMI_AVAILABLE

image

VBMI_UNAVAILABLE

image

BASE_VERSION
image

Performance

ON ICX -

BASE_VERSION vs VBMI_UNAVAILABLE

image

BASE_VERSION vs VBMI_AVAILABLE
image

Author:DeepakRajendrakumaran
Assignees:-
Labels:

area-System.Buffers, community-contribution, needs-area-label

Milestone:-

@DeepakRajendrakumaran

Copy link
Copy Markdown
ContributorAuthor

I am not an expert in THIRD-PARTY-NOTICES.TXT 🙂 but seems like the link to that article is worth adding here https://github.com/dotnet/runtime/blob/main/THIRD-PARTY-NOTICES.TXT#L345

There is an AVX512 based implementation in there - https://github.com/aklomp/base64/tree/master/lib/arch/avx512.

Do we use any of the code from that repo? I see it has BSD-2 license

Not directly but the logic(including shuffle constants are similar). But this implementation uses '_mm512_multishift_epi64_epi8' and that's not the one I'm using. This(https://github.com/WojciechMula/base64simd/blob/master/encode/encode.avx512vbmi.cpp) in particular is probably worth mentioning in hindsight(Since I used the non multishift version in my implementation with VBMI)

I used the below as resources to understand available implementations and available options(But they are all related). Which brings up the question which of these exactly I should be referencing

esp this for understanding : http://0x80.pl/notesen/2016-04-03-avx512-base64.html#id29

https://github.com/WojciechMula/base64simd/tree/masterhttps://arxiv.org/pdf/1910.05109.pdfhttps://github.com/lemire/fastbase64/blob/master/src/fastavx512bwbase64.chttps://github.com/aklomp/base64/tree/master/lib/arch/avx512

@EgorBo I modified the reference to point to https://github.com/WojciechMula/base64simd/tree/master. Which has the closest versions to the implementation I went with. Will this require me adding anything to notice?

@DeepakRajendrakumaran

Copy link
Copy Markdown
ContributorAuthor

I am not an expert in THIRD-PARTY-NOTICES.TXT 🙂 but seems like the link to that article is worth adding here https://github.com/dotnet/runtime/blob/main/THIRD-PARTY-NOTICES.TXT#L345

There is an AVX512 based implementation in there - https://github.com/aklomp/base64/tree/master/lib/arch/avx512.

Do we use any of the code from that repo? I see it has BSD-2 license

Not directly but the logic(including shuffle constants are similar). But this implementation uses '_mm512_multishift_epi64_epi8' and that's not the one I'm using. This(https://github.com/WojciechMula/base64simd/blob/master/encode/encode.avx512vbmi.cpp) in particular is probably worth mentioning in hindsight(Since I used the non multishift version in my implementation with VBMI)
I used the below as resources to understand available implementations and available options(But they are all related). Which brings up the question which of these exactly I should be referencing
esp this for understanding : http://0x80.pl/notesen/2016-04-03-avx512-base64.html#id29
https://github.com/WojciechMula/base64simd/tree/masterhttps://arxiv.org/pdf/1910.05109.pdfhttps://github.com/lemire/fastbase64/blob/master/src/fastavx512bwbase64.chttps://github.com/aklomp/base64/tree/master/lib/arch/avx512

@EgorBo I modified the reference to point to https://github.com/WojciechMula/base64simd/tree/master. Which has the closest versions to the implementation I went with. Will this require me adding anything to notice?

Have updated THIRD PARTY NOTICE based on conversation with @tannergooding . Removing fallback avx512Bw path meant I had to add only 2 references.

@EgorBoEgorBo left a comment

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.

Thanks! Looks way simpler now

@BruceForstallBruceForstall added avx512 Related to the AVX-512 architecture and removed needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners labels Sep 25, 2023
@BruceForstallBruceForstall added this to the 9.0.0 milestone Sep 25, 2023
@DeepakRajendrakumaran

Copy link
Copy Markdown
ContributorAuthor

@tannergooding@BruceForstall Any comments on this? I'd be great if we can move this forward this week,

@BruceForstall

Copy link
Copy Markdown
Contributor

I'm not the right person to review this. If @tannergooding can't review, maybe @stephentoub can review (or pick an appropriate reviewer).

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.

This comment isn't quite accurate.

Vector512.IsHardwareAccelerated can be made to return true for Skylake-X and up to before IceLake via an environment variable. This is why the caller has the check for Vector512.IsHardwareAccelerated && Avx512Vbmi.IsSupported and why this function has [CompExactlyDependsOn(typeof(Avx512Vbmi))]

We're fine with it not being usable pre IceLake since those often incur heavier downclocking and its unnecessary complexity for a non-default scenario.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Removed line 667

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: Most other places in the JIT we do str.Store(dest) since its an extension method and can be accessed using instance syntax.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I'm not sure I fully understand how this works

image

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.

It's likely conflicting because dest is a byte* while str is a Vector512<sbyte> and so it can't resolve

str.Store((sbyte*)dest) should fix it, or str.AsByte().Store(dest). The former is less IL, most notably.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Ah..I messed up and was using str.AsSbyte().Store(dest) It's fixed now. Thank you

@tannergoodingtannergooding left a comment

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.

LGTM. Just a request to cleanup a couple minor things.

@DeepakRajendrakumaran
DeepakRajendrakumaranforce-pushed the encoding branch 2 times, most recently from 4b2f7d1 to fc05bebCompareOctober 24, 2023 20:28
@DeepakRajendrakumaran

Copy link
Copy Markdown
ContributorAuthor

LGTM. Just a request to cleanup a couple minor things.

I've committed the clean-up changes. Please let me know if you want me to make any other changes

@tannergooding
tannergooding merged commit 9ad24ae into dotnet:mainOct 25, 2023
liveans pushed a commit to liveans/dotnet-runtime that referenced this pull request Nov 9, 2023
* Adding AVX512 path to Base64 encoding/Decoding
* Addressing review Comments.
Signed-off-by: Deepak Rajendrakumaran <deepak.rajendrakumaran@intel.com>
* Removing fallback path.
* Updating Third Party Notice.
* Addressing review comments
---------
Signed-off-by: Deepak Rajendrakumaran <deepak.rajendrakumaran@intel.com>
@ghostghost locked as resolved and limited conversation to collaborators Nov 24, 2023
@DeepakRajendrakumaran
DeepakRajendrakumaran deleted the encoding branch August 3, 2026 23:43
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Buffersavx512Related to the AVX-512 architecturecommunity-contributionIndicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants

@DeepakRajendrakumaran@danmoseley@EgorBo@BruceForstall@tannergooding@MihaZupan@marek-safar
, '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

Adding AVX512 path to Base64 encoding/Decoding - #92241

Merged
tannergooding merged 5 commits into
dotnet:mainfrom
DeepakRajendrakumaran:encoding
Oct 25, 2023
Merged

Adding AVX512 path to Base64 encoding/Decoding#92241
tannergooding merged 5 commits into
dotnet:mainfrom
DeepakRajendrakumaran:encoding

Conversation

@DeepakRajendrakumaran

Copy link
Copy Markdown
Contributor

Overview

This PR implements an AVX512 code path for Base64 encoding/Decoding. This is based on the work by Wojciech Muła and Daniel Lemire. There is a fast AVX512VBMI path and the fallback uses AVX512F/BW - I'll refer to these as VBMI_AVAILABLE and VBMI_UNAVAILABLE here on. For performance purposes, this will be compared to an AVX2 implementation which will be referred to as BASE_Version
Reference for the algorithm:

This version uses intrinsics directly and not generic vector libraries due to lack of current support in JIt/Vector libraries to produce optimal code. Some additional support which would be required in order to use generic vector library for implementing this would be

  1. Add ShuffleUnsafe for Vector512
  2. Extend Vector512.Shuffle() to lower to intrinsics instead of going to fallback for more cases.
  3. Expand Vector512 surface area to incorporate more high level functions

Even the current implementation can be further optimized by adding the multishift() implementation. This is a further optimization

Generated code

(Will be focusing on the actual encoding/decoding code within the loop only)

Encoding

VBMI_AVAILABLE

image

VBMI_UNAVAILABLE

image

BASE_VERSION
image

Decoding

VBMI_AVAILABLE

image

VBMI_UNAVAILABLE

image

BASE_VERSION
image

Performance

ON ICX -

BASE_VERSION vs VBMI_UNAVAILABLE

image

BASE_VERSION vs VBMI_AVAILABLE
image

@ghostghost added needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners community-contribution Indicates that the PR has been added by a community member labels Sep 18, 2023
@DeepakRajendrakumaran

Copy link
Copy Markdown
ContributorAuthor

@BruceForstall@tannergooding @dotnet/avx512-contrib

@danmoseley

Copy link
Copy Markdown
Contributor

Do we need a new entry in the third party notices file?

@EgorBo

Copy link
Copy Markdown
Member

Do we need a new entry in the third party notices file?

We should already have them if I am not mistaken (unless avx512 uses a different article)

@DeepakRajendrakumaran

Copy link
Copy Markdown
ContributorAuthor

Do we need a new entry in the third party notices file?

We should already have them if I am not mistaken (unless avx512 uses a different article)

I'm not sure about this-

The original sse and avx implementations use a similar algorithm and this is the reference provided - https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Base64Encoder.cs#L13-L14.

This implementation(the VBMI version) uses a modified version based on this(https://github.com/dotnet/runtime/pull/92241/files#diff-db463201901c2d83d2b563871ae11fafee9d5afe94e4d014b77212996b25f770R635) - https://arxiv.org/pdf/1910.05109.pdf

There is an AVX512 based implementation in there - https://github.com/aklomp/base64/tree/master/lib/arch/avx512. But it has only the encode and it requires 'multishift' which we do not currently support

@danmoseley

Copy link
Copy Markdown
Contributor

We generally acknowledge significant reuse in the TPN file even if there's a link from the sources. I see

License notice for vectorized base64 encoding / decoding
but I'm not sure it points to that pdf (eg it doesn't include Lemire in the list)

but, whatever @EgorBo recommends..

@EgorBo

Copy link
Copy Markdown
Member

I am not an expert in THIRD-PARTY-NOTICES.TXT 🙂 but seems like the link to that article is worth adding here https://github.com/dotnet/runtime/blob/main/THIRD-PARTY-NOTICES.TXT#L345

There is an AVX512 based implementation in there - https://github.com/aklomp/base64/tree/master/lib/arch/avx512.

Do we use any of the code from that repo? I see it has BSD-2 license

@DeepakRajendrakumaran

Copy link
Copy Markdown
ContributorAuthor

I am not an expert in THIRD-PARTY-NOTICES.TXT 🙂 but seems like the link to that article is worth adding here https://github.com/dotnet/runtime/blob/main/THIRD-PARTY-NOTICES.TXT#L345

There is an AVX512 based implementation in there - https://github.com/aklomp/base64/tree/master/lib/arch/avx512.

Do we use any of the code from that repo? I see it has BSD-2 license

Not directly but the logic(including shuffle constants are similar). But this implementation uses '_mm512_multishift_epi64_epi8' and that's not the one I'm using. This(https://github.com/WojciechMula/base64simd/blob/master/encode/encode.avx512vbmi.cpp) in particular is probably worth mentioning in hindsight(Since I used the non multishift version in my implementation with VBMI)

I used the below as resources to understand available implementations and available options(But they are all related). Which brings up the question which of these exactly I should be referencing

esp this for understanding : http://0x80.pl/notesen/2016-04-03-avx512-base64.html#id29

https://github.com/WojciechMula/base64simd/tree/master
https://arxiv.org/pdf/1910.05109.pdf
https://github.com/lemire/fastbase64/blob/master/src/fastavx512bwbase64.c
https://github.com/aklomp/base64/tree/master/lib/arch/avx512

@ghost

Copy link
Copy Markdown

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

Issue Details

Overview

This PR implements an AVX512 code path for Base64 encoding/Decoding. This is based on the work by Wojciech Muła and Daniel Lemire. There is a fast AVX512VBMI path and the fallback uses AVX512F/BW - I'll refer to these as VBMI_AVAILABLE and VBMI_UNAVAILABLE here on. For performance purposes, this will be compared to an AVX2 implementation which will be referred to as BASE_Version
Reference for the algorithm:

This version uses intrinsics directly and not generic vector libraries due to lack of current support in JIt/Vector libraries to produce optimal code. Some additional support which would be required in order to use generic vector library for implementing this would be

  1. Add ShuffleUnsafe for Vector512
  2. Extend Vector512.Shuffle() to lower to intrinsics instead of going to fallback for more cases.
  3. Expand Vector512 surface area to incorporate more high level functions

Even the current implementation can be further optimized by adding the multishift() implementation. This is a further optimization

Generated code

(Will be focusing on the actual encoding/decoding code within the loop only)

Encoding

VBMI_AVAILABLE

image

VBMI_UNAVAILABLE

image

BASE_VERSION
image

Decoding

VBMI_AVAILABLE

image

VBMI_UNAVAILABLE

image

BASE_VERSION
image

Performance

ON ICX -

BASE_VERSION vs VBMI_UNAVAILABLE

image

BASE_VERSION vs VBMI_AVAILABLE
image

Author:DeepakRajendrakumaran
Assignees:-
Labels:

area-System.Buffers, community-contribution, needs-area-label

Milestone:-

@DeepakRajendrakumaran

Copy link
Copy Markdown
ContributorAuthor

I am not an expert in THIRD-PARTY-NOTICES.TXT 🙂 but seems like the link to that article is worth adding here https://github.com/dotnet/runtime/blob/main/THIRD-PARTY-NOTICES.TXT#L345

There is an AVX512 based implementation in there - https://github.com/aklomp/base64/tree/master/lib/arch/avx512.

Do we use any of the code from that repo? I see it has BSD-2 license

Not directly but the logic(including shuffle constants are similar). But this implementation uses '_mm512_multishift_epi64_epi8' and that's not the one I'm using. This(https://github.com/WojciechMula/base64simd/blob/master/encode/encode.avx512vbmi.cpp) in particular is probably worth mentioning in hindsight(Since I used the non multishift version in my implementation with VBMI)

I used the below as resources to understand available implementations and available options(But they are all related). Which brings up the question which of these exactly I should be referencing

esp this for understanding : http://0x80.pl/notesen/2016-04-03-avx512-base64.html#id29

https://github.com/WojciechMula/base64simd/tree/masterhttps://arxiv.org/pdf/1910.05109.pdfhttps://github.com/lemire/fastbase64/blob/master/src/fastavx512bwbase64.chttps://github.com/aklomp/base64/tree/master/lib/arch/avx512

@EgorBo I modified the reference to point to https://github.com/WojciechMula/base64simd/tree/master. Which has the closest versions to the implementation I went with. Will this require me adding anything to notice?

@DeepakRajendrakumaran

Copy link
Copy Markdown
ContributorAuthor

I am not an expert in THIRD-PARTY-NOTICES.TXT 🙂 but seems like the link to that article is worth adding here https://github.com/dotnet/runtime/blob/main/THIRD-PARTY-NOTICES.TXT#L345

There is an AVX512 based implementation in there - https://github.com/aklomp/base64/tree/master/lib/arch/avx512.

Do we use any of the code from that repo? I see it has BSD-2 license

Not directly but the logic(including shuffle constants are similar). But this implementation uses '_mm512_multishift_epi64_epi8' and that's not the one I'm using. This(https://github.com/WojciechMula/base64simd/blob/master/encode/encode.avx512vbmi.cpp) in particular is probably worth mentioning in hindsight(Since I used the non multishift version in my implementation with VBMI)
I used the below as resources to understand available implementations and available options(But they are all related). Which brings up the question which of these exactly I should be referencing
esp this for understanding : http://0x80.pl/notesen/2016-04-03-avx512-base64.html#id29
https://github.com/WojciechMula/base64simd/tree/masterhttps://arxiv.org/pdf/1910.05109.pdfhttps://github.com/lemire/fastbase64/blob/master/src/fastavx512bwbase64.chttps://github.com/aklomp/base64/tree/master/lib/arch/avx512

@EgorBo I modified the reference to point to https://github.com/WojciechMula/base64simd/tree/master. Which has the closest versions to the implementation I went with. Will this require me adding anything to notice?

Have updated THIRD PARTY NOTICE based on conversation with @tannergooding . Removing fallback avx512Bw path meant I had to add only 2 references.

@EgorBoEgorBo left a comment

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.

Thanks! Looks way simpler now

@BruceForstallBruceForstall added avx512 Related to the AVX-512 architecture and removed needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners labels Sep 25, 2023
@BruceForstallBruceForstall added this to the 9.0.0 milestone Sep 25, 2023
@DeepakRajendrakumaran

Copy link
Copy Markdown
ContributorAuthor

@tannergooding@BruceForstall Any comments on this? I'd be great if we can move this forward this week,

@BruceForstall

Copy link
Copy Markdown
Contributor

I'm not the right person to review this. If @tannergooding can't review, maybe @stephentoub can review (or pick an appropriate reviewer).

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.

This comment isn't quite accurate.

Vector512.IsHardwareAccelerated can be made to return true for Skylake-X and up to before IceLake via an environment variable. This is why the caller has the check for Vector512.IsHardwareAccelerated && Avx512Vbmi.IsSupported and why this function has [CompExactlyDependsOn(typeof(Avx512Vbmi))]

We're fine with it not being usable pre IceLake since those often incur heavier downclocking and its unnecessary complexity for a non-default scenario.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Removed line 667

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: Most other places in the JIT we do str.Store(dest) since its an extension method and can be accessed using instance syntax.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I'm not sure I fully understand how this works

image

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.

It's likely conflicting because dest is a byte* while str is a Vector512<sbyte> and so it can't resolve

str.Store((sbyte*)dest) should fix it, or str.AsByte().Store(dest). The former is less IL, most notably.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Ah..I messed up and was using str.AsSbyte().Store(dest) It's fixed now. Thank you

@tannergoodingtannergooding left a comment

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.

LGTM. Just a request to cleanup a couple minor things.

@DeepakRajendrakumaran
DeepakRajendrakumaranforce-pushed the encoding branch 2 times, most recently from 4b2f7d1 to fc05bebCompareOctober 24, 2023 20:28
@DeepakRajendrakumaran

Copy link
Copy Markdown
ContributorAuthor

LGTM. Just a request to cleanup a couple minor things.

I've committed the clean-up changes. Please let me know if you want me to make any other changes

@tannergooding
tannergooding merged commit 9ad24ae into dotnet:mainOct 25, 2023
liveans pushed a commit to liveans/dotnet-runtime that referenced this pull request Nov 9, 2023
* Adding AVX512 path to Base64 encoding/Decoding
* Addressing review Comments.
Signed-off-by: Deepak Rajendrakumaran <deepak.rajendrakumaran@intel.com>
* Removing fallback path.
* Updating Third Party Notice.
* Addressing review comments
---------
Signed-off-by: Deepak Rajendrakumaran <deepak.rajendrakumaran@intel.com>
@ghostghost locked as resolved and limited conversation to collaborators Nov 24, 2023
@DeepakRajendrakumaran
DeepakRajendrakumaran deleted the encoding branch August 3, 2026 23:43
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Buffersavx512Related to the AVX-512 architecturecommunity-contributionIndicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants

@DeepakRajendrakumaran@danmoseley@EgorBo@BruceForstall@tannergooding@MihaZupan@marek-safar
, '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

Adding AVX512 path to Base64 encoding/Decoding - #92241

Merged
tannergooding merged 5 commits into
dotnet:mainfrom
DeepakRajendrakumaran:encoding
Oct 25, 2023
Merged

Adding AVX512 path to Base64 encoding/Decoding#92241
tannergooding merged 5 commits into
dotnet:mainfrom
DeepakRajendrakumaran:encoding

Conversation

@DeepakRajendrakumaran

Copy link
Copy Markdown
Contributor

Overview

This PR implements an AVX512 code path for Base64 encoding/Decoding. This is based on the work by Wojciech Muła and Daniel Lemire. There is a fast AVX512VBMI path and the fallback uses AVX512F/BW - I'll refer to these as VBMI_AVAILABLE and VBMI_UNAVAILABLE here on. For performance purposes, this will be compared to an AVX2 implementation which will be referred to as BASE_Version
Reference for the algorithm:

This version uses intrinsics directly and not generic vector libraries due to lack of current support in JIt/Vector libraries to produce optimal code. Some additional support which would be required in order to use generic vector library for implementing this would be

  1. Add ShuffleUnsafe for Vector512
  2. Extend Vector512.Shuffle() to lower to intrinsics instead of going to fallback for more cases.
  3. Expand Vector512 surface area to incorporate more high level functions

Even the current implementation can be further optimized by adding the multishift() implementation. This is a further optimization

Generated code

(Will be focusing on the actual encoding/decoding code within the loop only)

Encoding

VBMI_AVAILABLE

image

VBMI_UNAVAILABLE

image

BASE_VERSION
image

Decoding

VBMI_AVAILABLE

image

VBMI_UNAVAILABLE

image

BASE_VERSION
image

Performance

ON ICX -

BASE_VERSION vs VBMI_UNAVAILABLE

image

BASE_VERSION vs VBMI_AVAILABLE
image

@ghostghost added needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners community-contribution Indicates that the PR has been added by a community member labels Sep 18, 2023
@DeepakRajendrakumaran

Copy link
Copy Markdown
ContributorAuthor

@BruceForstall@tannergooding @dotnet/avx512-contrib

@danmoseley

Copy link
Copy Markdown
Contributor

Do we need a new entry in the third party notices file?

@EgorBo

Copy link
Copy Markdown
Member

Do we need a new entry in the third party notices file?

We should already have them if I am not mistaken (unless avx512 uses a different article)

@DeepakRajendrakumaran

Copy link
Copy Markdown
ContributorAuthor

Do we need a new entry in the third party notices file?

We should already have them if I am not mistaken (unless avx512 uses a different article)

I'm not sure about this-

The original sse and avx implementations use a similar algorithm and this is the reference provided - https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Base64Encoder.cs#L13-L14.

This implementation(the VBMI version) uses a modified version based on this(https://github.com/dotnet/runtime/pull/92241/files#diff-db463201901c2d83d2b563871ae11fafee9d5afe94e4d014b77212996b25f770R635) - https://arxiv.org/pdf/1910.05109.pdf

There is an AVX512 based implementation in there - https://github.com/aklomp/base64/tree/master/lib/arch/avx512. But it has only the encode and it requires 'multishift' which we do not currently support

@danmoseley

Copy link
Copy Markdown
Contributor

We generally acknowledge significant reuse in the TPN file even if there's a link from the sources. I see

License notice for vectorized base64 encoding / decoding
but I'm not sure it points to that pdf (eg it doesn't include Lemire in the list)

but, whatever @EgorBo recommends..

@EgorBo

Copy link
Copy Markdown
Member

I am not an expert in THIRD-PARTY-NOTICES.TXT 🙂 but seems like the link to that article is worth adding here https://github.com/dotnet/runtime/blob/main/THIRD-PARTY-NOTICES.TXT#L345

There is an AVX512 based implementation in there - https://github.com/aklomp/base64/tree/master/lib/arch/avx512.

Do we use any of the code from that repo? I see it has BSD-2 license

@DeepakRajendrakumaran

Copy link
Copy Markdown
ContributorAuthor

I am not an expert in THIRD-PARTY-NOTICES.TXT 🙂 but seems like the link to that article is worth adding here https://github.com/dotnet/runtime/blob/main/THIRD-PARTY-NOTICES.TXT#L345

There is an AVX512 based implementation in there - https://github.com/aklomp/base64/tree/master/lib/arch/avx512.

Do we use any of the code from that repo? I see it has BSD-2 license

Not directly but the logic(including shuffle constants are similar). But this implementation uses '_mm512_multishift_epi64_epi8' and that's not the one I'm using. This(https://github.com/WojciechMula/base64simd/blob/master/encode/encode.avx512vbmi.cpp) in particular is probably worth mentioning in hindsight(Since I used the non multishift version in my implementation with VBMI)

I used the below as resources to understand available implementations and available options(But they are all related). Which brings up the question which of these exactly I should be referencing

esp this for understanding : http://0x80.pl/notesen/2016-04-03-avx512-base64.html#id29

https://github.com/WojciechMula/base64simd/tree/master
https://arxiv.org/pdf/1910.05109.pdf
https://github.com/lemire/fastbase64/blob/master/src/fastavx512bwbase64.c
https://github.com/aklomp/base64/tree/master/lib/arch/avx512

@ghost

Copy link
Copy Markdown

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

Issue Details

Overview

This PR implements an AVX512 code path for Base64 encoding/Decoding. This is based on the work by Wojciech Muła and Daniel Lemire. There is a fast AVX512VBMI path and the fallback uses AVX512F/BW - I'll refer to these as VBMI_AVAILABLE and VBMI_UNAVAILABLE here on. For performance purposes, this will be compared to an AVX2 implementation which will be referred to as BASE_Version
Reference for the algorithm:

This version uses intrinsics directly and not generic vector libraries due to lack of current support in JIt/Vector libraries to produce optimal code. Some additional support which would be required in order to use generic vector library for implementing this would be

  1. Add ShuffleUnsafe for Vector512
  2. Extend Vector512.Shuffle() to lower to intrinsics instead of going to fallback for more cases.
  3. Expand Vector512 surface area to incorporate more high level functions

Even the current implementation can be further optimized by adding the multishift() implementation. This is a further optimization

Generated code

(Will be focusing on the actual encoding/decoding code within the loop only)

Encoding

VBMI_AVAILABLE

image

VBMI_UNAVAILABLE

image

BASE_VERSION
image

Decoding

VBMI_AVAILABLE

image

VBMI_UNAVAILABLE

image

BASE_VERSION
image

Performance

ON ICX -

BASE_VERSION vs VBMI_UNAVAILABLE

image

BASE_VERSION vs VBMI_AVAILABLE
image

Author:DeepakRajendrakumaran
Assignees:-
Labels:

area-System.Buffers, community-contribution, needs-area-label

Milestone:-

@DeepakRajendrakumaran

Copy link
Copy Markdown
ContributorAuthor

I am not an expert in THIRD-PARTY-NOTICES.TXT 🙂 but seems like the link to that article is worth adding here https://github.com/dotnet/runtime/blob/main/THIRD-PARTY-NOTICES.TXT#L345

There is an AVX512 based implementation in there - https://github.com/aklomp/base64/tree/master/lib/arch/avx512.

Do we use any of the code from that repo? I see it has BSD-2 license

Not directly but the logic(including shuffle constants are similar). But this implementation uses '_mm512_multishift_epi64_epi8' and that's not the one I'm using. This(https://github.com/WojciechMula/base64simd/blob/master/encode/encode.avx512vbmi.cpp) in particular is probably worth mentioning in hindsight(Since I used the non multishift version in my implementation with VBMI)

I used the below as resources to understand available implementations and available options(But they are all related). Which brings up the question which of these exactly I should be referencing

esp this for understanding : http://0x80.pl/notesen/2016-04-03-avx512-base64.html#id29

https://github.com/WojciechMula/base64simd/tree/masterhttps://arxiv.org/pdf/1910.05109.pdfhttps://github.com/lemire/fastbase64/blob/master/src/fastavx512bwbase64.chttps://github.com/aklomp/base64/tree/master/lib/arch/avx512

@EgorBo I modified the reference to point to https://github.com/WojciechMula/base64simd/tree/master. Which has the closest versions to the implementation I went with. Will this require me adding anything to notice?

@DeepakRajendrakumaran

Copy link
Copy Markdown
ContributorAuthor

I am not an expert in THIRD-PARTY-NOTICES.TXT 🙂 but seems like the link to that article is worth adding here https://github.com/dotnet/runtime/blob/main/THIRD-PARTY-NOTICES.TXT#L345

There is an AVX512 based implementation in there - https://github.com/aklomp/base64/tree/master/lib/arch/avx512.

Do we use any of the code from that repo? I see it has BSD-2 license

Not directly but the logic(including shuffle constants are similar). But this implementation uses '_mm512_multishift_epi64_epi8' and that's not the one I'm using. This(https://github.com/WojciechMula/base64simd/blob/master/encode/encode.avx512vbmi.cpp) in particular is probably worth mentioning in hindsight(Since I used the non multishift version in my implementation with VBMI)
I used the below as resources to understand available implementations and available options(But they are all related). Which brings up the question which of these exactly I should be referencing
esp this for understanding : http://0x80.pl/notesen/2016-04-03-avx512-base64.html#id29
https://github.com/WojciechMula/base64simd/tree/masterhttps://arxiv.org/pdf/1910.05109.pdfhttps://github.com/lemire/fastbase64/blob/master/src/fastavx512bwbase64.chttps://github.com/aklomp/base64/tree/master/lib/arch/avx512

@EgorBo I modified the reference to point to https://github.com/WojciechMula/base64simd/tree/master. Which has the closest versions to the implementation I went with. Will this require me adding anything to notice?

Have updated THIRD PARTY NOTICE based on conversation with @tannergooding . Removing fallback avx512Bw path meant I had to add only 2 references.

@EgorBoEgorBo left a comment

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.

Thanks! Looks way simpler now

@BruceForstallBruceForstall added avx512 Related to the AVX-512 architecture and removed needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners labels Sep 25, 2023
@BruceForstallBruceForstall added this to the 9.0.0 milestone Sep 25, 2023
@DeepakRajendrakumaran

Copy link
Copy Markdown
ContributorAuthor

@tannergooding@BruceForstall Any comments on this? I'd be great if we can move this forward this week,

@BruceForstall

Copy link
Copy Markdown
Contributor

I'm not the right person to review this. If @tannergooding can't review, maybe @stephentoub can review (or pick an appropriate reviewer).

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.

This comment isn't quite accurate.

Vector512.IsHardwareAccelerated can be made to return true for Skylake-X and up to before IceLake via an environment variable. This is why the caller has the check for Vector512.IsHardwareAccelerated && Avx512Vbmi.IsSupported and why this function has [CompExactlyDependsOn(typeof(Avx512Vbmi))]

We're fine with it not being usable pre IceLake since those often incur heavier downclocking and its unnecessary complexity for a non-default scenario.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Removed line 667

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: Most other places in the JIT we do str.Store(dest) since its an extension method and can be accessed using instance syntax.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I'm not sure I fully understand how this works

image

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.

It's likely conflicting because dest is a byte* while str is a Vector512<sbyte> and so it can't resolve

str.Store((sbyte*)dest) should fix it, or str.AsByte().Store(dest). The former is less IL, most notably.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Ah..I messed up and was using str.AsSbyte().Store(dest) It's fixed now. Thank you

@tannergoodingtannergooding left a comment

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.

LGTM. Just a request to cleanup a couple minor things.

@DeepakRajendrakumaran
DeepakRajendrakumaranforce-pushed the encoding branch 2 times, most recently from 4b2f7d1 to fc05bebCompareOctober 24, 2023 20:28
@DeepakRajendrakumaran

Copy link
Copy Markdown
ContributorAuthor

LGTM. Just a request to cleanup a couple minor things.

I've committed the clean-up changes. Please let me know if you want me to make any other changes

@tannergooding
tannergooding merged commit 9ad24ae into dotnet:mainOct 25, 2023
liveans pushed a commit to liveans/dotnet-runtime that referenced this pull request Nov 9, 2023
* Adding AVX512 path to Base64 encoding/Decoding
* Addressing review Comments.
Signed-off-by: Deepak Rajendrakumaran <deepak.rajendrakumaran@intel.com>
* Removing fallback path.
* Updating Third Party Notice.
* Addressing review comments
---------
Signed-off-by: Deepak Rajendrakumaran <deepak.rajendrakumaran@intel.com>
@ghostghost locked as resolved and limited conversation to collaborators Nov 24, 2023
@DeepakRajendrakumaran
DeepakRajendrakumaran deleted the encoding branch August 3, 2026 23:43
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Buffersavx512Related to the AVX-512 architecturecommunity-contributionIndicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants

@DeepakRajendrakumaran@danmoseley@EgorBo@BruceForstall@tannergooding@MihaZupan@marek-safar
, '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

Adding AVX512 path to Base64 encoding/Decoding - #92241

Merged
tannergooding merged 5 commits into
dotnet:mainfrom
DeepakRajendrakumaran:encoding
Oct 25, 2023
Merged

Adding AVX512 path to Base64 encoding/Decoding#92241
tannergooding merged 5 commits into
dotnet:mainfrom
DeepakRajendrakumaran:encoding

Conversation

@DeepakRajendrakumaran

Copy link
Copy Markdown
Contributor

Overview

This PR implements an AVX512 code path for Base64 encoding/Decoding. This is based on the work by Wojciech Muła and Daniel Lemire. There is a fast AVX512VBMI path and the fallback uses AVX512F/BW - I'll refer to these as VBMI_AVAILABLE and VBMI_UNAVAILABLE here on. For performance purposes, this will be compared to an AVX2 implementation which will be referred to as BASE_Version
Reference for the algorithm:

This version uses intrinsics directly and not generic vector libraries due to lack of current support in JIt/Vector libraries to produce optimal code. Some additional support which would be required in order to use generic vector library for implementing this would be

  1. Add ShuffleUnsafe for Vector512
  2. Extend Vector512.Shuffle() to lower to intrinsics instead of going to fallback for more cases.
  3. Expand Vector512 surface area to incorporate more high level functions

Even the current implementation can be further optimized by adding the multishift() implementation. This is a further optimization

Generated code

(Will be focusing on the actual encoding/decoding code within the loop only)

Encoding

VBMI_AVAILABLE

image

VBMI_UNAVAILABLE

image

BASE_VERSION
image

Decoding

VBMI_AVAILABLE

image

VBMI_UNAVAILABLE

image

BASE_VERSION
image

Performance

ON ICX -

BASE_VERSION vs VBMI_UNAVAILABLE

image

BASE_VERSION vs VBMI_AVAILABLE
image

@ghostghost added needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners community-contribution Indicates that the PR has been added by a community member labels Sep 18, 2023
@DeepakRajendrakumaran

Copy link
Copy Markdown
ContributorAuthor

@BruceForstall@tannergooding @dotnet/avx512-contrib

@danmoseley

Copy link
Copy Markdown
Contributor

Do we need a new entry in the third party notices file?

@EgorBo

Copy link
Copy Markdown
Member

Do we need a new entry in the third party notices file?

We should already have them if I am not mistaken (unless avx512 uses a different article)

@DeepakRajendrakumaran

Copy link
Copy Markdown
ContributorAuthor

Do we need a new entry in the third party notices file?

We should already have them if I am not mistaken (unless avx512 uses a different article)

I'm not sure about this-

The original sse and avx implementations use a similar algorithm and this is the reference provided - https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Base64Encoder.cs#L13-L14.

This implementation(the VBMI version) uses a modified version based on this(https://github.com/dotnet/runtime/pull/92241/files#diff-db463201901c2d83d2b563871ae11fafee9d5afe94e4d014b77212996b25f770R635) - https://arxiv.org/pdf/1910.05109.pdf

There is an AVX512 based implementation in there - https://github.com/aklomp/base64/tree/master/lib/arch/avx512. But it has only the encode and it requires 'multishift' which we do not currently support

@danmoseley

Copy link
Copy Markdown
Contributor

We generally acknowledge significant reuse in the TPN file even if there's a link from the sources. I see

License notice for vectorized base64 encoding / decoding
but I'm not sure it points to that pdf (eg it doesn't include Lemire in the list)

but, whatever @EgorBo recommends..

@EgorBo

Copy link
Copy Markdown
Member

I am not an expert in THIRD-PARTY-NOTICES.TXT 🙂 but seems like the link to that article is worth adding here https://github.com/dotnet/runtime/blob/main/THIRD-PARTY-NOTICES.TXT#L345

There is an AVX512 based implementation in there - https://github.com/aklomp/base64/tree/master/lib/arch/avx512.

Do we use any of the code from that repo? I see it has BSD-2 license

@DeepakRajendrakumaran

Copy link
Copy Markdown
ContributorAuthor

I am not an expert in THIRD-PARTY-NOTICES.TXT 🙂 but seems like the link to that article is worth adding here https://github.com/dotnet/runtime/blob/main/THIRD-PARTY-NOTICES.TXT#L345

There is an AVX512 based implementation in there - https://github.com/aklomp/base64/tree/master/lib/arch/avx512.

Do we use any of the code from that repo? I see it has BSD-2 license

Not directly but the logic(including shuffle constants are similar). But this implementation uses '_mm512_multishift_epi64_epi8' and that's not the one I'm using. This(https://github.com/WojciechMula/base64simd/blob/master/encode/encode.avx512vbmi.cpp) in particular is probably worth mentioning in hindsight(Since I used the non multishift version in my implementation with VBMI)

I used the below as resources to understand available implementations and available options(But they are all related). Which brings up the question which of these exactly I should be referencing

esp this for understanding : http://0x80.pl/notesen/2016-04-03-avx512-base64.html#id29

https://github.com/WojciechMula/base64simd/tree/master
https://arxiv.org/pdf/1910.05109.pdf
https://github.com/lemire/fastbase64/blob/master/src/fastavx512bwbase64.c
https://github.com/aklomp/base64/tree/master/lib/arch/avx512

@ghost

Copy link
Copy Markdown

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

Issue Details

Overview

This PR implements an AVX512 code path for Base64 encoding/Decoding. This is based on the work by Wojciech Muła and Daniel Lemire. There is a fast AVX512VBMI path and the fallback uses AVX512F/BW - I'll refer to these as VBMI_AVAILABLE and VBMI_UNAVAILABLE here on. For performance purposes, this will be compared to an AVX2 implementation which will be referred to as BASE_Version
Reference for the algorithm:

This version uses intrinsics directly and not generic vector libraries due to lack of current support in JIt/Vector libraries to produce optimal code. Some additional support which would be required in order to use generic vector library for implementing this would be

  1. Add ShuffleUnsafe for Vector512
  2. Extend Vector512.Shuffle() to lower to intrinsics instead of going to fallback for more cases.
  3. Expand Vector512 surface area to incorporate more high level functions

Even the current implementation can be further optimized by adding the multishift() implementation. This is a further optimization

Generated code

(Will be focusing on the actual encoding/decoding code within the loop only)

Encoding

VBMI_AVAILABLE

image

VBMI_UNAVAILABLE

image

BASE_VERSION
image

Decoding

VBMI_AVAILABLE

image

VBMI_UNAVAILABLE

image

BASE_VERSION
image

Performance

ON ICX -

BASE_VERSION vs VBMI_UNAVAILABLE

image

BASE_VERSION vs VBMI_AVAILABLE
image

Author:DeepakRajendrakumaran
Assignees:-
Labels:

area-System.Buffers, community-contribution, needs-area-label

Milestone:-

@DeepakRajendrakumaran

Copy link
Copy Markdown
ContributorAuthor

I am not an expert in THIRD-PARTY-NOTICES.TXT 🙂 but seems like the link to that article is worth adding here https://github.com/dotnet/runtime/blob/main/THIRD-PARTY-NOTICES.TXT#L345

There is an AVX512 based implementation in there - https://github.com/aklomp/base64/tree/master/lib/arch/avx512.

Do we use any of the code from that repo? I see it has BSD-2 license

Not directly but the logic(including shuffle constants are similar). But this implementation uses '_mm512_multishift_epi64_epi8' and that's not the one I'm using. This(https://github.com/WojciechMula/base64simd/blob/master/encode/encode.avx512vbmi.cpp) in particular is probably worth mentioning in hindsight(Since I used the non multishift version in my implementation with VBMI)

I used the below as resources to understand available implementations and available options(But they are all related). Which brings up the question which of these exactly I should be referencing

esp this for understanding : http://0x80.pl/notesen/2016-04-03-avx512-base64.html#id29

https://github.com/WojciechMula/base64simd/tree/masterhttps://arxiv.org/pdf/1910.05109.pdfhttps://github.com/lemire/fastbase64/blob/master/src/fastavx512bwbase64.chttps://github.com/aklomp/base64/tree/master/lib/arch/avx512

@EgorBo I modified the reference to point to https://github.com/WojciechMula/base64simd/tree/master. Which has the closest versions to the implementation I went with. Will this require me adding anything to notice?

@DeepakRajendrakumaran

Copy link
Copy Markdown
ContributorAuthor

I am not an expert in THIRD-PARTY-NOTICES.TXT 🙂 but seems like the link to that article is worth adding here https://github.com/dotnet/runtime/blob/main/THIRD-PARTY-NOTICES.TXT#L345

There is an AVX512 based implementation in there - https://github.com/aklomp/base64/tree/master/lib/arch/avx512.

Do we use any of the code from that repo? I see it has BSD-2 license

Not directly but the logic(including shuffle constants are similar). But this implementation uses '_mm512_multishift_epi64_epi8' and that's not the one I'm using. This(https://github.com/WojciechMula/base64simd/blob/master/encode/encode.avx512vbmi.cpp) in particular is probably worth mentioning in hindsight(Since I used the non multishift version in my implementation with VBMI)
I used the below as resources to understand available implementations and available options(But they are all related). Which brings up the question which of these exactly I should be referencing
esp this for understanding : http://0x80.pl/notesen/2016-04-03-avx512-base64.html#id29
https://github.com/WojciechMula/base64simd/tree/masterhttps://arxiv.org/pdf/1910.05109.pdfhttps://github.com/lemire/fastbase64/blob/master/src/fastavx512bwbase64.chttps://github.com/aklomp/base64/tree/master/lib/arch/avx512

@EgorBo I modified the reference to point to https://github.com/WojciechMula/base64simd/tree/master. Which has the closest versions to the implementation I went with. Will this require me adding anything to notice?

Have updated THIRD PARTY NOTICE based on conversation with @tannergooding . Removing fallback avx512Bw path meant I had to add only 2 references.

@EgorBoEgorBo left a comment

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.

Thanks! Looks way simpler now

@BruceForstallBruceForstall added avx512 Related to the AVX-512 architecture and removed needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners labels Sep 25, 2023
@BruceForstallBruceForstall added this to the 9.0.0 milestone Sep 25, 2023
@DeepakRajendrakumaran

Copy link
Copy Markdown
ContributorAuthor

@tannergooding@BruceForstall Any comments on this? I'd be great if we can move this forward this week,

@BruceForstall

Copy link
Copy Markdown
Contributor

I'm not the right person to review this. If @tannergooding can't review, maybe @stephentoub can review (or pick an appropriate reviewer).

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.

This comment isn't quite accurate.

Vector512.IsHardwareAccelerated can be made to return true for Skylake-X and up to before IceLake via an environment variable. This is why the caller has the check for Vector512.IsHardwareAccelerated && Avx512Vbmi.IsSupported and why this function has [CompExactlyDependsOn(typeof(Avx512Vbmi))]

We're fine with it not being usable pre IceLake since those often incur heavier downclocking and its unnecessary complexity for a non-default scenario.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Removed line 667

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: Most other places in the JIT we do str.Store(dest) since its an extension method and can be accessed using instance syntax.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I'm not sure I fully understand how this works

image

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.

It's likely conflicting because dest is a byte* while str is a Vector512<sbyte> and so it can't resolve

str.Store((sbyte*)dest) should fix it, or str.AsByte().Store(dest). The former is less IL, most notably.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Ah..I messed up and was using str.AsSbyte().Store(dest) It's fixed now. Thank you

@tannergoodingtannergooding left a comment

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.

LGTM. Just a request to cleanup a couple minor things.

@DeepakRajendrakumaran
DeepakRajendrakumaranforce-pushed the encoding branch 2 times, most recently from 4b2f7d1 to fc05bebCompareOctober 24, 2023 20:28
@DeepakRajendrakumaran

Copy link
Copy Markdown
ContributorAuthor

LGTM. Just a request to cleanup a couple minor things.

I've committed the clean-up changes. Please let me know if you want me to make any other changes

@tannergooding
tannergooding merged commit 9ad24ae into dotnet:mainOct 25, 2023
liveans pushed a commit to liveans/dotnet-runtime that referenced this pull request Nov 9, 2023
* Adding AVX512 path to Base64 encoding/Decoding
* Addressing review Comments.
Signed-off-by: Deepak Rajendrakumaran <deepak.rajendrakumaran@intel.com>
* Removing fallback path.
* Updating Third Party Notice.
* Addressing review comments
---------
Signed-off-by: Deepak Rajendrakumaran <deepak.rajendrakumaran@intel.com>
@ghostghost locked as resolved and limited conversation to collaborators Nov 24, 2023
@DeepakRajendrakumaran
DeepakRajendrakumaran deleted the encoding branch August 3, 2026 23:43
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Buffersavx512Related to the AVX-512 architecturecommunity-contributionIndicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants

@DeepakRajendrakumaran@danmoseley@EgorBo@BruceForstall@tannergooding@MihaZupan@marek-safar
, '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

Adding AVX512 path to Base64 encoding/Decoding - #92241

Merged
tannergooding merged 5 commits into
dotnet:mainfrom
DeepakRajendrakumaran:encoding
Oct 25, 2023
Merged

Adding AVX512 path to Base64 encoding/Decoding#92241
tannergooding merged 5 commits into
dotnet:mainfrom
DeepakRajendrakumaran:encoding

Conversation

@DeepakRajendrakumaran

Copy link
Copy Markdown
Contributor

Overview

This PR implements an AVX512 code path for Base64 encoding/Decoding. This is based on the work by Wojciech Muła and Daniel Lemire. There is a fast AVX512VBMI path and the fallback uses AVX512F/BW - I'll refer to these as VBMI_AVAILABLE and VBMI_UNAVAILABLE here on. For performance purposes, this will be compared to an AVX2 implementation which will be referred to as BASE_Version
Reference for the algorithm:

This version uses intrinsics directly and not generic vector libraries due to lack of current support in JIt/Vector libraries to produce optimal code. Some additional support which would be required in order to use generic vector library for implementing this would be

  1. Add ShuffleUnsafe for Vector512
  2. Extend Vector512.Shuffle() to lower to intrinsics instead of going to fallback for more cases.
  3. Expand Vector512 surface area to incorporate more high level functions

Even the current implementation can be further optimized by adding the multishift() implementation. This is a further optimization

Generated code

(Will be focusing on the actual encoding/decoding code within the loop only)

Encoding

VBMI_AVAILABLE

image

VBMI_UNAVAILABLE

image

BASE_VERSION
image

Decoding

VBMI_AVAILABLE

image

VBMI_UNAVAILABLE

image

BASE_VERSION
image

Performance

ON ICX -

BASE_VERSION vs VBMI_UNAVAILABLE

image

BASE_VERSION vs VBMI_AVAILABLE
image

@ghostghost added needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners community-contribution Indicates that the PR has been added by a community member labels Sep 18, 2023
@DeepakRajendrakumaran

Copy link
Copy Markdown
ContributorAuthor

@BruceForstall@tannergooding @dotnet/avx512-contrib

@danmoseley

Copy link
Copy Markdown
Contributor

Do we need a new entry in the third party notices file?

@EgorBo

Copy link
Copy Markdown
Member

Do we need a new entry in the third party notices file?

We should already have them if I am not mistaken (unless avx512 uses a different article)

@DeepakRajendrakumaran

Copy link
Copy Markdown
ContributorAuthor

Do we need a new entry in the third party notices file?

We should already have them if I am not mistaken (unless avx512 uses a different article)

I'm not sure about this-

The original sse and avx implementations use a similar algorithm and this is the reference provided - https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Base64Encoder.cs#L13-L14.

This implementation(the VBMI version) uses a modified version based on this(https://github.com/dotnet/runtime/pull/92241/files#diff-db463201901c2d83d2b563871ae11fafee9d5afe94e4d014b77212996b25f770R635) - https://arxiv.org/pdf/1910.05109.pdf

There is an AVX512 based implementation in there - https://github.com/aklomp/base64/tree/master/lib/arch/avx512. But it has only the encode and it requires 'multishift' which we do not currently support

@danmoseley

Copy link
Copy Markdown
Contributor

We generally acknowledge significant reuse in the TPN file even if there's a link from the sources. I see

License notice for vectorized base64 encoding / decoding
but I'm not sure it points to that pdf (eg it doesn't include Lemire in the list)

but, whatever @EgorBo recommends..

@EgorBo

Copy link
Copy Markdown
Member

I am not an expert in THIRD-PARTY-NOTICES.TXT 🙂 but seems like the link to that article is worth adding here https://github.com/dotnet/runtime/blob/main/THIRD-PARTY-NOTICES.TXT#L345

There is an AVX512 based implementation in there - https://github.com/aklomp/base64/tree/master/lib/arch/avx512.

Do we use any of the code from that repo? I see it has BSD-2 license

@DeepakRajendrakumaran

Copy link
Copy Markdown
ContributorAuthor

I am not an expert in THIRD-PARTY-NOTICES.TXT 🙂 but seems like the link to that article is worth adding here https://github.com/dotnet/runtime/blob/main/THIRD-PARTY-NOTICES.TXT#L345

There is an AVX512 based implementation in there - https://github.com/aklomp/base64/tree/master/lib/arch/avx512.

Do we use any of the code from that repo? I see it has BSD-2 license

Not directly but the logic(including shuffle constants are similar). But this implementation uses '_mm512_multishift_epi64_epi8' and that's not the one I'm using. This(https://github.com/WojciechMula/base64simd/blob/master/encode/encode.avx512vbmi.cpp) in particular is probably worth mentioning in hindsight(Since I used the non multishift version in my implementation with VBMI)

I used the below as resources to understand available implementations and available options(But they are all related). Which brings up the question which of these exactly I should be referencing

esp this for understanding : http://0x80.pl/notesen/2016-04-03-avx512-base64.html#id29

https://github.com/WojciechMula/base64simd/tree/master
https://arxiv.org/pdf/1910.05109.pdf
https://github.com/lemire/fastbase64/blob/master/src/fastavx512bwbase64.c
https://github.com/aklomp/base64/tree/master/lib/arch/avx512

@ghost

Copy link
Copy Markdown

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

Issue Details

Overview

This PR implements an AVX512 code path for Base64 encoding/Decoding. This is based on the work by Wojciech Muła and Daniel Lemire. There is a fast AVX512VBMI path and the fallback uses AVX512F/BW - I'll refer to these as VBMI_AVAILABLE and VBMI_UNAVAILABLE here on. For performance purposes, this will be compared to an AVX2 implementation which will be referred to as BASE_Version
Reference for the algorithm:

This version uses intrinsics directly and not generic vector libraries due to lack of current support in JIt/Vector libraries to produce optimal code. Some additional support which would be required in order to use generic vector library for implementing this would be

  1. Add ShuffleUnsafe for Vector512
  2. Extend Vector512.Shuffle() to lower to intrinsics instead of going to fallback for more cases.
  3. Expand Vector512 surface area to incorporate more high level functions

Even the current implementation can be further optimized by adding the multishift() implementation. This is a further optimization

Generated code

(Will be focusing on the actual encoding/decoding code within the loop only)

Encoding

VBMI_AVAILABLE

image

VBMI_UNAVAILABLE

image

BASE_VERSION
image

Decoding

VBMI_AVAILABLE

image

VBMI_UNAVAILABLE

image

BASE_VERSION
image

Performance

ON ICX -

BASE_VERSION vs VBMI_UNAVAILABLE

image

BASE_VERSION vs VBMI_AVAILABLE
image

Author:DeepakRajendrakumaran
Assignees:-
Labels:

area-System.Buffers, community-contribution, needs-area-label

Milestone:-

@DeepakRajendrakumaran

Copy link
Copy Markdown
ContributorAuthor

I am not an expert in THIRD-PARTY-NOTICES.TXT 🙂 but seems like the link to that article is worth adding here https://github.com/dotnet/runtime/blob/main/THIRD-PARTY-NOTICES.TXT#L345

There is an AVX512 based implementation in there - https://github.com/aklomp/base64/tree/master/lib/arch/avx512.

Do we use any of the code from that repo? I see it has BSD-2 license

Not directly but the logic(including shuffle constants are similar). But this implementation uses '_mm512_multishift_epi64_epi8' and that's not the one I'm using. This(https://github.com/WojciechMula/base64simd/blob/master/encode/encode.avx512vbmi.cpp) in particular is probably worth mentioning in hindsight(Since I used the non multishift version in my implementation with VBMI)

I used the below as resources to understand available implementations and available options(But they are all related). Which brings up the question which of these exactly I should be referencing

esp this for understanding : http://0x80.pl/notesen/2016-04-03-avx512-base64.html#id29

https://github.com/WojciechMula/base64simd/tree/masterhttps://arxiv.org/pdf/1910.05109.pdfhttps://github.com/lemire/fastbase64/blob/master/src/fastavx512bwbase64.chttps://github.com/aklomp/base64/tree/master/lib/arch/avx512

@EgorBo I modified the reference to point to https://github.com/WojciechMula/base64simd/tree/master. Which has the closest versions to the implementation I went with. Will this require me adding anything to notice?

@DeepakRajendrakumaran

Copy link
Copy Markdown
ContributorAuthor

I am not an expert in THIRD-PARTY-NOTICES.TXT 🙂 but seems like the link to that article is worth adding here https://github.com/dotnet/runtime/blob/main/THIRD-PARTY-NOTICES.TXT#L345

There is an AVX512 based implementation in there - https://github.com/aklomp/base64/tree/master/lib/arch/avx512.

Do we use any of the code from that repo? I see it has BSD-2 license

Not directly but the logic(including shuffle constants are similar). But this implementation uses '_mm512_multishift_epi64_epi8' and that's not the one I'm using. This(https://github.com/WojciechMula/base64simd/blob/master/encode/encode.avx512vbmi.cpp) in particular is probably worth mentioning in hindsight(Since I used the non multishift version in my implementation with VBMI)
I used the below as resources to understand available implementations and available options(But they are all related). Which brings up the question which of these exactly I should be referencing
esp this for understanding : http://0x80.pl/notesen/2016-04-03-avx512-base64.html#id29
https://github.com/WojciechMula/base64simd/tree/masterhttps://arxiv.org/pdf/1910.05109.pdfhttps://github.com/lemire/fastbase64/blob/master/src/fastavx512bwbase64.chttps://github.com/aklomp/base64/tree/master/lib/arch/avx512

@EgorBo I modified the reference to point to https://github.com/WojciechMula/base64simd/tree/master. Which has the closest versions to the implementation I went with. Will this require me adding anything to notice?

Have updated THIRD PARTY NOTICE based on conversation with @tannergooding . Removing fallback avx512Bw path meant I had to add only 2 references.

@EgorBoEgorBo left a comment

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.

Thanks! Looks way simpler now

@BruceForstallBruceForstall added avx512 Related to the AVX-512 architecture and removed needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners labels Sep 25, 2023
@BruceForstallBruceForstall added this to the 9.0.0 milestone Sep 25, 2023
@DeepakRajendrakumaran

Copy link
Copy Markdown
ContributorAuthor

@tannergooding@BruceForstall Any comments on this? I'd be great if we can move this forward this week,

@BruceForstall

Copy link
Copy Markdown
Contributor

I'm not the right person to review this. If @tannergooding can't review, maybe @stephentoub can review (or pick an appropriate reviewer).

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.

This comment isn't quite accurate.

Vector512.IsHardwareAccelerated can be made to return true for Skylake-X and up to before IceLake via an environment variable. This is why the caller has the check for Vector512.IsHardwareAccelerated && Avx512Vbmi.IsSupported and why this function has [CompExactlyDependsOn(typeof(Avx512Vbmi))]

We're fine with it not being usable pre IceLake since those often incur heavier downclocking and its unnecessary complexity for a non-default scenario.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Removed line 667

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: Most other places in the JIT we do str.Store(dest) since its an extension method and can be accessed using instance syntax.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I'm not sure I fully understand how this works

image

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.

It's likely conflicting because dest is a byte* while str is a Vector512<sbyte> and so it can't resolve

str.Store((sbyte*)dest) should fix it, or str.AsByte().Store(dest). The former is less IL, most notably.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Ah..I messed up and was using str.AsSbyte().Store(dest) It's fixed now. Thank you

@tannergoodingtannergooding left a comment

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.

LGTM. Just a request to cleanup a couple minor things.

@DeepakRajendrakumaran
DeepakRajendrakumaranforce-pushed the encoding branch 2 times, most recently from 4b2f7d1 to fc05bebCompareOctober 24, 2023 20:28
@DeepakRajendrakumaran

Copy link
Copy Markdown
ContributorAuthor

LGTM. Just a request to cleanup a couple minor things.

I've committed the clean-up changes. Please let me know if you want me to make any other changes

@tannergooding
tannergooding merged commit 9ad24ae into dotnet:mainOct 25, 2023
liveans pushed a commit to liveans/dotnet-runtime that referenced this pull request Nov 9, 2023
* Adding AVX512 path to Base64 encoding/Decoding
* Addressing review Comments.
Signed-off-by: Deepak Rajendrakumaran <deepak.rajendrakumaran@intel.com>
* Removing fallback path.
* Updating Third Party Notice.
* Addressing review comments
---------
Signed-off-by: Deepak Rajendrakumaran <deepak.rajendrakumaran@intel.com>
@ghostghost locked as resolved and limited conversation to collaborators Nov 24, 2023
@DeepakRajendrakumaran
DeepakRajendrakumaran deleted the encoding branch August 3, 2026 23:43
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Buffersavx512Related to the AVX-512 architecturecommunity-contributionIndicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants

@DeepakRajendrakumaran@danmoseley@EgorBo@BruceForstall@tannergooding@MihaZupan@marek-safar
, '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

Adding AVX512 path to Base64 encoding/Decoding - #92241

Merged
tannergooding merged 5 commits into
dotnet:mainfrom
DeepakRajendrakumaran:encoding
Oct 25, 2023
Merged

Adding AVX512 path to Base64 encoding/Decoding#92241
tannergooding merged 5 commits into
dotnet:mainfrom
DeepakRajendrakumaran:encoding

Conversation

@DeepakRajendrakumaran

Copy link
Copy Markdown
Contributor

Overview

This PR implements an AVX512 code path for Base64 encoding/Decoding. This is based on the work by Wojciech Muła and Daniel Lemire. There is a fast AVX512VBMI path and the fallback uses AVX512F/BW - I'll refer to these as VBMI_AVAILABLE and VBMI_UNAVAILABLE here on. For performance purposes, this will be compared to an AVX2 implementation which will be referred to as BASE_Version
Reference for the algorithm:

This version uses intrinsics directly and not generic vector libraries due to lack of current support in JIt/Vector libraries to produce optimal code. Some additional support which would be required in order to use generic vector library for implementing this would be

  1. Add ShuffleUnsafe for Vector512
  2. Extend Vector512.Shuffle() to lower to intrinsics instead of going to fallback for more cases.
  3. Expand Vector512 surface area to incorporate more high level functions

Even the current implementation can be further optimized by adding the multishift() implementation. This is a further optimization

Generated code

(Will be focusing on the actual encoding/decoding code within the loop only)

Encoding

VBMI_AVAILABLE

image

VBMI_UNAVAILABLE

image

BASE_VERSION
image

Decoding

VBMI_AVAILABLE

image

VBMI_UNAVAILABLE

image

BASE_VERSION
image

Performance

ON ICX -

BASE_VERSION vs VBMI_UNAVAILABLE

image

BASE_VERSION vs VBMI_AVAILABLE
image

@ghostghost added needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners community-contribution Indicates that the PR has been added by a community member labels Sep 18, 2023
@DeepakRajendrakumaran

Copy link
Copy Markdown
ContributorAuthor

@BruceForstall@tannergooding @dotnet/avx512-contrib

@danmoseley

Copy link
Copy Markdown
Contributor

Do we need a new entry in the third party notices file?

@EgorBo

Copy link
Copy Markdown
Member

Do we need a new entry in the third party notices file?

We should already have them if I am not mistaken (unless avx512 uses a different article)

@DeepakRajendrakumaran

Copy link
Copy Markdown
ContributorAuthor

Do we need a new entry in the third party notices file?

We should already have them if I am not mistaken (unless avx512 uses a different article)

I'm not sure about this-

The original sse and avx implementations use a similar algorithm and this is the reference provided - https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Base64Encoder.cs#L13-L14.

This implementation(the VBMI version) uses a modified version based on this(https://github.com/dotnet/runtime/pull/92241/files#diff-db463201901c2d83d2b563871ae11fafee9d5afe94e4d014b77212996b25f770R635) - https://arxiv.org/pdf/1910.05109.pdf

There is an AVX512 based implementation in there - https://github.com/aklomp/base64/tree/master/lib/arch/avx512. But it has only the encode and it requires 'multishift' which we do not currently support

@danmoseley

Copy link
Copy Markdown
Contributor

We generally acknowledge significant reuse in the TPN file even if there's a link from the sources. I see

License notice for vectorized base64 encoding / decoding
but I'm not sure it points to that pdf (eg it doesn't include Lemire in the list)

but, whatever @EgorBo recommends..

@EgorBo

Copy link
Copy Markdown
Member

I am not an expert in THIRD-PARTY-NOTICES.TXT 🙂 but seems like the link to that article is worth adding here https://github.com/dotnet/runtime/blob/main/THIRD-PARTY-NOTICES.TXT#L345

There is an AVX512 based implementation in there - https://github.com/aklomp/base64/tree/master/lib/arch/avx512.

Do we use any of the code from that repo? I see it has BSD-2 license

@DeepakRajendrakumaran

Copy link
Copy Markdown
ContributorAuthor

I am not an expert in THIRD-PARTY-NOTICES.TXT 🙂 but seems like the link to that article is worth adding here https://github.com/dotnet/runtime/blob/main/THIRD-PARTY-NOTICES.TXT#L345

There is an AVX512 based implementation in there - https://github.com/aklomp/base64/tree/master/lib/arch/avx512.

Do we use any of the code from that repo? I see it has BSD-2 license

Not directly but the logic(including shuffle constants are similar). But this implementation uses '_mm512_multishift_epi64_epi8' and that's not the one I'm using. This(https://github.com/WojciechMula/base64simd/blob/master/encode/encode.avx512vbmi.cpp) in particular is probably worth mentioning in hindsight(Since I used the non multishift version in my implementation with VBMI)

I used the below as resources to understand available implementations and available options(But they are all related). Which brings up the question which of these exactly I should be referencing

esp this for understanding : http://0x80.pl/notesen/2016-04-03-avx512-base64.html#id29

https://github.com/WojciechMula/base64simd/tree/master
https://arxiv.org/pdf/1910.05109.pdf
https://github.com/lemire/fastbase64/blob/master/src/fastavx512bwbase64.c
https://github.com/aklomp/base64/tree/master/lib/arch/avx512

@ghost

Copy link
Copy Markdown

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

Issue Details

Overview

This PR implements an AVX512 code path for Base64 encoding/Decoding. This is based on the work by Wojciech Muła and Daniel Lemire. There is a fast AVX512VBMI path and the fallback uses AVX512F/BW - I'll refer to these as VBMI_AVAILABLE and VBMI_UNAVAILABLE here on. For performance purposes, this will be compared to an AVX2 implementation which will be referred to as BASE_Version
Reference for the algorithm:

This version uses intrinsics directly and not generic vector libraries due to lack of current support in JIt/Vector libraries to produce optimal code. Some additional support which would be required in order to use generic vector library for implementing this would be

  1. Add ShuffleUnsafe for Vector512
  2. Extend Vector512.Shuffle() to lower to intrinsics instead of going to fallback for more cases.
  3. Expand Vector512 surface area to incorporate more high level functions

Even the current implementation can be further optimized by adding the multishift() implementation. This is a further optimization

Generated code

(Will be focusing on the actual encoding/decoding code within the loop only)

Encoding

VBMI_AVAILABLE

image

VBMI_UNAVAILABLE

image

BASE_VERSION
image

Decoding

VBMI_AVAILABLE

image

VBMI_UNAVAILABLE

image

BASE_VERSION
image

Performance

ON ICX -

BASE_VERSION vs VBMI_UNAVAILABLE

image

BASE_VERSION vs VBMI_AVAILABLE
image

Author:DeepakRajendrakumaran
Assignees:-
Labels:

area-System.Buffers, community-contribution, needs-area-label

Milestone:-

@DeepakRajendrakumaran

Copy link
Copy Markdown
ContributorAuthor

I am not an expert in THIRD-PARTY-NOTICES.TXT 🙂 but seems like the link to that article is worth adding here https://github.com/dotnet/runtime/blob/main/THIRD-PARTY-NOTICES.TXT#L345

There is an AVX512 based implementation in there - https://github.com/aklomp/base64/tree/master/lib/arch/avx512.

Do we use any of the code from that repo? I see it has BSD-2 license

Not directly but the logic(including shuffle constants are similar). But this implementation uses '_mm512_multishift_epi64_epi8' and that's not the one I'm using. This(https://github.com/WojciechMula/base64simd/blob/master/encode/encode.avx512vbmi.cpp) in particular is probably worth mentioning in hindsight(Since I used the non multishift version in my implementation with VBMI)

I used the below as resources to understand available implementations and available options(But they are all related). Which brings up the question which of these exactly I should be referencing

esp this for understanding : http://0x80.pl/notesen/2016-04-03-avx512-base64.html#id29

https://github.com/WojciechMula/base64simd/tree/masterhttps://arxiv.org/pdf/1910.05109.pdfhttps://github.com/lemire/fastbase64/blob/master/src/fastavx512bwbase64.chttps://github.com/aklomp/base64/tree/master/lib/arch/avx512

@EgorBo I modified the reference to point to https://github.com/WojciechMula/base64simd/tree/master. Which has the closest versions to the implementation I went with. Will this require me adding anything to notice?

@DeepakRajendrakumaran

Copy link
Copy Markdown
ContributorAuthor

I am not an expert in THIRD-PARTY-NOTICES.TXT 🙂 but seems like the link to that article is worth adding here https://github.com/dotnet/runtime/blob/main/THIRD-PARTY-NOTICES.TXT#L345

There is an AVX512 based implementation in there - https://github.com/aklomp/base64/tree/master/lib/arch/avx512.

Do we use any of the code from that repo? I see it has BSD-2 license

Not directly but the logic(including shuffle constants are similar). But this implementation uses '_mm512_multishift_epi64_epi8' and that's not the one I'm using. This(https://github.com/WojciechMula/base64simd/blob/master/encode/encode.avx512vbmi.cpp) in particular is probably worth mentioning in hindsight(Since I used the non multishift version in my implementation with VBMI)
I used the below as resources to understand available implementations and available options(But they are all related). Which brings up the question which of these exactly I should be referencing
esp this for understanding : http://0x80.pl/notesen/2016-04-03-avx512-base64.html#id29
https://github.com/WojciechMula/base64simd/tree/masterhttps://arxiv.org/pdf/1910.05109.pdfhttps://github.com/lemire/fastbase64/blob/master/src/fastavx512bwbase64.chttps://github.com/aklomp/base64/tree/master/lib/arch/avx512

@EgorBo I modified the reference to point to https://github.com/WojciechMula/base64simd/tree/master. Which has the closest versions to the implementation I went with. Will this require me adding anything to notice?

Have updated THIRD PARTY NOTICE based on conversation with @tannergooding . Removing fallback avx512Bw path meant I had to add only 2 references.

@EgorBoEgorBo left a comment

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.

Thanks! Looks way simpler now

@BruceForstallBruceForstall added avx512 Related to the AVX-512 architecture and removed needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners labels Sep 25, 2023
@BruceForstallBruceForstall added this to the 9.0.0 milestone Sep 25, 2023
@DeepakRajendrakumaran

Copy link
Copy Markdown
ContributorAuthor

@tannergooding@BruceForstall Any comments on this? I'd be great if we can move this forward this week,

@BruceForstall

Copy link
Copy Markdown
Contributor

I'm not the right person to review this. If @tannergooding can't review, maybe @stephentoub can review (or pick an appropriate reviewer).

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.

This comment isn't quite accurate.

Vector512.IsHardwareAccelerated can be made to return true for Skylake-X and up to before IceLake via an environment variable. This is why the caller has the check for Vector512.IsHardwareAccelerated && Avx512Vbmi.IsSupported and why this function has [CompExactlyDependsOn(typeof(Avx512Vbmi))]

We're fine with it not being usable pre IceLake since those often incur heavier downclocking and its unnecessary complexity for a non-default scenario.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Removed line 667

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: Most other places in the JIT we do str.Store(dest) since its an extension method and can be accessed using instance syntax.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I'm not sure I fully understand how this works

image

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.

It's likely conflicting because dest is a byte* while str is a Vector512<sbyte> and so it can't resolve

str.Store((sbyte*)dest) should fix it, or str.AsByte().Store(dest). The former is less IL, most notably.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Ah..I messed up and was using str.AsSbyte().Store(dest) It's fixed now. Thank you

@tannergoodingtannergooding left a comment

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.

LGTM. Just a request to cleanup a couple minor things.

@DeepakRajendrakumaran
DeepakRajendrakumaranforce-pushed the encoding branch 2 times, most recently from 4b2f7d1 to fc05bebCompareOctober 24, 2023 20:28
@DeepakRajendrakumaran

Copy link
Copy Markdown
ContributorAuthor

LGTM. Just a request to cleanup a couple minor things.

I've committed the clean-up changes. Please let me know if you want me to make any other changes

@tannergooding
tannergooding merged commit 9ad24ae into dotnet:mainOct 25, 2023
liveans pushed a commit to liveans/dotnet-runtime that referenced this pull request Nov 9, 2023
* Adding AVX512 path to Base64 encoding/Decoding
* Addressing review Comments.
Signed-off-by: Deepak Rajendrakumaran <deepak.rajendrakumaran@intel.com>
* Removing fallback path.
* Updating Third Party Notice.
* Addressing review comments
---------
Signed-off-by: Deepak Rajendrakumaran <deepak.rajendrakumaran@intel.com>
@ghostghost locked as resolved and limited conversation to collaborators Nov 24, 2023
@DeepakRajendrakumaran
DeepakRajendrakumaran deleted the encoding branch August 3, 2026 23:43
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Buffersavx512Related to the AVX-512 architecturecommunity-contributionIndicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants

@DeepakRajendrakumaran@danmoseley@EgorBo@BruceForstall@tannergooding@MihaZupan@marek-safar
, '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

Adding AVX512 path to Base64 encoding/Decoding - #92241

Merged
tannergooding merged 5 commits into
dotnet:mainfrom
DeepakRajendrakumaran:encoding
Oct 25, 2023
Merged

Adding AVX512 path to Base64 encoding/Decoding#92241
tannergooding merged 5 commits into
dotnet:mainfrom
DeepakRajendrakumaran:encoding

Conversation

@DeepakRajendrakumaran

Copy link
Copy Markdown
Contributor

Overview

This PR implements an AVX512 code path for Base64 encoding/Decoding. This is based on the work by Wojciech Muła and Daniel Lemire. There is a fast AVX512VBMI path and the fallback uses AVX512F/BW - I'll refer to these as VBMI_AVAILABLE and VBMI_UNAVAILABLE here on. For performance purposes, this will be compared to an AVX2 implementation which will be referred to as BASE_Version
Reference for the algorithm:

This version uses intrinsics directly and not generic vector libraries due to lack of current support in JIt/Vector libraries to produce optimal code. Some additional support which would be required in order to use generic vector library for implementing this would be

  1. Add ShuffleUnsafe for Vector512
  2. Extend Vector512.Shuffle() to lower to intrinsics instead of going to fallback for more cases.
  3. Expand Vector512 surface area to incorporate more high level functions

Even the current implementation can be further optimized by adding the multishift() implementation. This is a further optimization

Generated code

(Will be focusing on the actual encoding/decoding code within the loop only)

Encoding

VBMI_AVAILABLE

image

VBMI_UNAVAILABLE

image

BASE_VERSION
image

Decoding

VBMI_AVAILABLE

image

VBMI_UNAVAILABLE

image

BASE_VERSION
image

Performance

ON ICX -

BASE_VERSION vs VBMI_UNAVAILABLE

image

BASE_VERSION vs VBMI_AVAILABLE
image

@ghostghost added needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners community-contribution Indicates that the PR has been added by a community member labels Sep 18, 2023
@DeepakRajendrakumaran

Copy link
Copy Markdown
ContributorAuthor

@BruceForstall@tannergooding @dotnet/avx512-contrib

@danmoseley

Copy link
Copy Markdown
Contributor

Do we need a new entry in the third party notices file?

@EgorBo

Copy link
Copy Markdown
Member

Do we need a new entry in the third party notices file?

We should already have them if I am not mistaken (unless avx512 uses a different article)

@DeepakRajendrakumaran

Copy link
Copy Markdown
ContributorAuthor

Do we need a new entry in the third party notices file?

We should already have them if I am not mistaken (unless avx512 uses a different article)

I'm not sure about this-

The original sse and avx implementations use a similar algorithm and this is the reference provided - https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Base64Encoder.cs#L13-L14.

This implementation(the VBMI version) uses a modified version based on this(https://github.com/dotnet/runtime/pull/92241/files#diff-db463201901c2d83d2b563871ae11fafee9d5afe94e4d014b77212996b25f770R635) - https://arxiv.org/pdf/1910.05109.pdf

There is an AVX512 based implementation in there - https://github.com/aklomp/base64/tree/master/lib/arch/avx512. But it has only the encode and it requires 'multishift' which we do not currently support

@danmoseley

Copy link
Copy Markdown
Contributor

We generally acknowledge significant reuse in the TPN file even if there's a link from the sources. I see

License notice for vectorized base64 encoding / decoding
but I'm not sure it points to that pdf (eg it doesn't include Lemire in the list)

but, whatever @EgorBo recommends..

@EgorBo

Copy link
Copy Markdown
Member

I am not an expert in THIRD-PARTY-NOTICES.TXT 🙂 but seems like the link to that article is worth adding here https://github.com/dotnet/runtime/blob/main/THIRD-PARTY-NOTICES.TXT#L345

There is an AVX512 based implementation in there - https://github.com/aklomp/base64/tree/master/lib/arch/avx512.

Do we use any of the code from that repo? I see it has BSD-2 license

@DeepakRajendrakumaran

Copy link
Copy Markdown
ContributorAuthor

I am not an expert in THIRD-PARTY-NOTICES.TXT 🙂 but seems like the link to that article is worth adding here https://github.com/dotnet/runtime/blob/main/THIRD-PARTY-NOTICES.TXT#L345

There is an AVX512 based implementation in there - https://github.com/aklomp/base64/tree/master/lib/arch/avx512.

Do we use any of the code from that repo? I see it has BSD-2 license

Not directly but the logic(including shuffle constants are similar). But this implementation uses '_mm512_multishift_epi64_epi8' and that's not the one I'm using. This(https://github.com/WojciechMula/base64simd/blob/master/encode/encode.avx512vbmi.cpp) in particular is probably worth mentioning in hindsight(Since I used the non multishift version in my implementation with VBMI)

I used the below as resources to understand available implementations and available options(But they are all related). Which brings up the question which of these exactly I should be referencing

esp this for understanding : http://0x80.pl/notesen/2016-04-03-avx512-base64.html#id29

https://github.com/WojciechMula/base64simd/tree/master
https://arxiv.org/pdf/1910.05109.pdf
https://github.com/lemire/fastbase64/blob/master/src/fastavx512bwbase64.c
https://github.com/aklomp/base64/tree/master/lib/arch/avx512

@ghost

Copy link
Copy Markdown

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

Issue Details

Overview

This PR implements an AVX512 code path for Base64 encoding/Decoding. This is based on the work by Wojciech Muła and Daniel Lemire. There is a fast AVX512VBMI path and the fallback uses AVX512F/BW - I'll refer to these as VBMI_AVAILABLE and VBMI_UNAVAILABLE here on. For performance purposes, this will be compared to an AVX2 implementation which will be referred to as BASE_Version
Reference for the algorithm:

This version uses intrinsics directly and not generic vector libraries due to lack of current support in JIt/Vector libraries to produce optimal code. Some additional support which would be required in order to use generic vector library for implementing this would be

  1. Add ShuffleUnsafe for Vector512
  2. Extend Vector512.Shuffle() to lower to intrinsics instead of going to fallback for more cases.
  3. Expand Vector512 surface area to incorporate more high level functions

Even the current implementation can be further optimized by adding the multishift() implementation. This is a further optimization

Generated code

(Will be focusing on the actual encoding/decoding code within the loop only)

Encoding

VBMI_AVAILABLE

image

VBMI_UNAVAILABLE

image

BASE_VERSION
image

Decoding

VBMI_AVAILABLE

image

VBMI_UNAVAILABLE

image

BASE_VERSION
image

Performance

ON ICX -

BASE_VERSION vs VBMI_UNAVAILABLE

image

BASE_VERSION vs VBMI_AVAILABLE
image

Author:DeepakRajendrakumaran
Assignees:-
Labels:

area-System.Buffers, community-contribution, needs-area-label

Milestone:-

@DeepakRajendrakumaran

Copy link
Copy Markdown
ContributorAuthor

I am not an expert in THIRD-PARTY-NOTICES.TXT 🙂 but seems like the link to that article is worth adding here https://github.com/dotnet/runtime/blob/main/THIRD-PARTY-NOTICES.TXT#L345

There is an AVX512 based implementation in there - https://github.com/aklomp/base64/tree/master/lib/arch/avx512.

Do we use any of the code from that repo? I see it has BSD-2 license

Not directly but the logic(including shuffle constants are similar). But this implementation uses '_mm512_multishift_epi64_epi8' and that's not the one I'm using. This(https://github.com/WojciechMula/base64simd/blob/master/encode/encode.avx512vbmi.cpp) in particular is probably worth mentioning in hindsight(Since I used the non multishift version in my implementation with VBMI)

I used the below as resources to understand available implementations and available options(But they are all related). Which brings up the question which of these exactly I should be referencing

esp this for understanding : http://0x80.pl/notesen/2016-04-03-avx512-base64.html#id29

https://github.com/WojciechMula/base64simd/tree/masterhttps://arxiv.org/pdf/1910.05109.pdfhttps://github.com/lemire/fastbase64/blob/master/src/fastavx512bwbase64.chttps://github.com/aklomp/base64/tree/master/lib/arch/avx512

@EgorBo I modified the reference to point to https://github.com/WojciechMula/base64simd/tree/master. Which has the closest versions to the implementation I went with. Will this require me adding anything to notice?

@DeepakRajendrakumaran

Copy link
Copy Markdown
ContributorAuthor

I am not an expert in THIRD-PARTY-NOTICES.TXT 🙂 but seems like the link to that article is worth adding here https://github.com/dotnet/runtime/blob/main/THIRD-PARTY-NOTICES.TXT#L345

There is an AVX512 based implementation in there - https://github.com/aklomp/base64/tree/master/lib/arch/avx512.

Do we use any of the code from that repo? I see it has BSD-2 license

Not directly but the logic(including shuffle constants are similar). But this implementation uses '_mm512_multishift_epi64_epi8' and that's not the one I'm using. This(https://github.com/WojciechMula/base64simd/blob/master/encode/encode.avx512vbmi.cpp) in particular is probably worth mentioning in hindsight(Since I used the non multishift version in my implementation with VBMI)
I used the below as resources to understand available implementations and available options(But they are all related). Which brings up the question which of these exactly I should be referencing
esp this for understanding : http://0x80.pl/notesen/2016-04-03-avx512-base64.html#id29
https://github.com/WojciechMula/base64simd/tree/masterhttps://arxiv.org/pdf/1910.05109.pdfhttps://github.com/lemire/fastbase64/blob/master/src/fastavx512bwbase64.chttps://github.com/aklomp/base64/tree/master/lib/arch/avx512

@EgorBo I modified the reference to point to https://github.com/WojciechMula/base64simd/tree/master. Which has the closest versions to the implementation I went with. Will this require me adding anything to notice?

Have updated THIRD PARTY NOTICE based on conversation with @tannergooding . Removing fallback avx512Bw path meant I had to add only 2 references.

@EgorBoEgorBo left a comment

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.

Thanks! Looks way simpler now

@BruceForstallBruceForstall added avx512 Related to the AVX-512 architecture and removed needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners labels Sep 25, 2023
@BruceForstallBruceForstall added this to the 9.0.0 milestone Sep 25, 2023
@DeepakRajendrakumaran

Copy link
Copy Markdown
ContributorAuthor

@tannergooding@BruceForstall Any comments on this? I'd be great if we can move this forward this week,

@BruceForstall

Copy link
Copy Markdown
Contributor

I'm not the right person to review this. If @tannergooding can't review, maybe @stephentoub can review (or pick an appropriate reviewer).

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.

This comment isn't quite accurate.

Vector512.IsHardwareAccelerated can be made to return true for Skylake-X and up to before IceLake via an environment variable. This is why the caller has the check for Vector512.IsHardwareAccelerated && Avx512Vbmi.IsSupported and why this function has [CompExactlyDependsOn(typeof(Avx512Vbmi))]

We're fine with it not being usable pre IceLake since those often incur heavier downclocking and its unnecessary complexity for a non-default scenario.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Removed line 667

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: Most other places in the JIT we do str.Store(dest) since its an extension method and can be accessed using instance syntax.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I'm not sure I fully understand how this works

image

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.

It's likely conflicting because dest is a byte* while str is a Vector512<sbyte> and so it can't resolve

str.Store((sbyte*)dest) should fix it, or str.AsByte().Store(dest). The former is less IL, most notably.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Ah..I messed up and was using str.AsSbyte().Store(dest) It's fixed now. Thank you

@tannergoodingtannergooding left a comment

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.

LGTM. Just a request to cleanup a couple minor things.

@DeepakRajendrakumaran
DeepakRajendrakumaranforce-pushed the encoding branch 2 times, most recently from 4b2f7d1 to fc05bebCompareOctober 24, 2023 20:28
@DeepakRajendrakumaran

Copy link
Copy Markdown
ContributorAuthor

LGTM. Just a request to cleanup a couple minor things.

I've committed the clean-up changes. Please let me know if you want me to make any other changes

@tannergooding
tannergooding merged commit 9ad24ae into dotnet:mainOct 25, 2023
liveans pushed a commit to liveans/dotnet-runtime that referenced this pull request Nov 9, 2023
* Adding AVX512 path to Base64 encoding/Decoding
* Addressing review Comments.
Signed-off-by: Deepak Rajendrakumaran <deepak.rajendrakumaran@intel.com>
* Removing fallback path.
* Updating Third Party Notice.
* Addressing review comments
---------
Signed-off-by: Deepak Rajendrakumaran <deepak.rajendrakumaran@intel.com>
@ghostghost locked as resolved and limited conversation to collaborators Nov 24, 2023
@DeepakRajendrakumaran
DeepakRajendrakumaran deleted the encoding branch August 3, 2026 23:43
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Buffersavx512Related to the AVX-512 architecturecommunity-contributionIndicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants

@DeepakRajendrakumaran@danmoseley@EgorBo@BruceForstall@tannergooding@MihaZupan@marek-safar
, '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

Adding AVX512 path to Base64 encoding/Decoding - #92241

Merged
tannergooding merged 5 commits into
dotnet:mainfrom
DeepakRajendrakumaran:encoding
Oct 25, 2023
Merged

Adding AVX512 path to Base64 encoding/Decoding#92241
tannergooding merged 5 commits into
dotnet:mainfrom
DeepakRajendrakumaran:encoding

Conversation

@DeepakRajendrakumaran

Copy link
Copy Markdown
Contributor

Overview

This PR implements an AVX512 code path for Base64 encoding/Decoding. This is based on the work by Wojciech Muła and Daniel Lemire. There is a fast AVX512VBMI path and the fallback uses AVX512F/BW - I'll refer to these as VBMI_AVAILABLE and VBMI_UNAVAILABLE here on. For performance purposes, this will be compared to an AVX2 implementation which will be referred to as BASE_Version
Reference for the algorithm:

This version uses intrinsics directly and not generic vector libraries due to lack of current support in JIt/Vector libraries to produce optimal code. Some additional support which would be required in order to use generic vector library for implementing this would be

  1. Add ShuffleUnsafe for Vector512
  2. Extend Vector512.Shuffle() to lower to intrinsics instead of going to fallback for more cases.
  3. Expand Vector512 surface area to incorporate more high level functions

Even the current implementation can be further optimized by adding the multishift() implementation. This is a further optimization

Generated code

(Will be focusing on the actual encoding/decoding code within the loop only)

Encoding

VBMI_AVAILABLE

image

VBMI_UNAVAILABLE

image

BASE_VERSION
image

Decoding

VBMI_AVAILABLE

image

VBMI_UNAVAILABLE

image

BASE_VERSION
image

Performance

ON ICX -

BASE_VERSION vs VBMI_UNAVAILABLE

image

BASE_VERSION vs VBMI_AVAILABLE
image

@ghostghost added needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners community-contribution Indicates that the PR has been added by a community member labels Sep 18, 2023
@DeepakRajendrakumaran

Copy link
Copy Markdown
ContributorAuthor

@BruceForstall@tannergooding @dotnet/avx512-contrib

@danmoseley

Copy link
Copy Markdown
Contributor

Do we need a new entry in the third party notices file?

@EgorBo

Copy link
Copy Markdown
Member

Do we need a new entry in the third party notices file?

We should already have them if I am not mistaken (unless avx512 uses a different article)

@DeepakRajendrakumaran

Copy link
Copy Markdown
ContributorAuthor

Do we need a new entry in the third party notices file?

We should already have them if I am not mistaken (unless avx512 uses a different article)

I'm not sure about this-

The original sse and avx implementations use a similar algorithm and this is the reference provided - https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Base64Encoder.cs#L13-L14.

This implementation(the VBMI version) uses a modified version based on this(https://github.com/dotnet/runtime/pull/92241/files#diff-db463201901c2d83d2b563871ae11fafee9d5afe94e4d014b77212996b25f770R635) - https://arxiv.org/pdf/1910.05109.pdf

There is an AVX512 based implementation in there - https://github.com/aklomp/base64/tree/master/lib/arch/avx512. But it has only the encode and it requires 'multishift' which we do not currently support

@danmoseley

Copy link
Copy Markdown
Contributor

We generally acknowledge significant reuse in the TPN file even if there's a link from the sources. I see

License notice for vectorized base64 encoding / decoding
but I'm not sure it points to that pdf (eg it doesn't include Lemire in the list)

but, whatever @EgorBo recommends..

@EgorBo

Copy link
Copy Markdown
Member

I am not an expert in THIRD-PARTY-NOTICES.TXT 🙂 but seems like the link to that article is worth adding here https://github.com/dotnet/runtime/blob/main/THIRD-PARTY-NOTICES.TXT#L345

There is an AVX512 based implementation in there - https://github.com/aklomp/base64/tree/master/lib/arch/avx512.

Do we use any of the code from that repo? I see it has BSD-2 license

@DeepakRajendrakumaran

Copy link
Copy Markdown
ContributorAuthor

I am not an expert in THIRD-PARTY-NOTICES.TXT 🙂 but seems like the link to that article is worth adding here https://github.com/dotnet/runtime/blob/main/THIRD-PARTY-NOTICES.TXT#L345

There is an AVX512 based implementation in there - https://github.com/aklomp/base64/tree/master/lib/arch/avx512.

Do we use any of the code from that repo? I see it has BSD-2 license

Not directly but the logic(including shuffle constants are similar). But this implementation uses '_mm512_multishift_epi64_epi8' and that's not the one I'm using. This(https://github.com/WojciechMula/base64simd/blob/master/encode/encode.avx512vbmi.cpp) in particular is probably worth mentioning in hindsight(Since I used the non multishift version in my implementation with VBMI)

I used the below as resources to understand available implementations and available options(But they are all related). Which brings up the question which of these exactly I should be referencing

esp this for understanding : http://0x80.pl/notesen/2016-04-03-avx512-base64.html#id29

https://github.com/WojciechMula/base64simd/tree/master
https://arxiv.org/pdf/1910.05109.pdf
https://github.com/lemire/fastbase64/blob/master/src/fastavx512bwbase64.c
https://github.com/aklomp/base64/tree/master/lib/arch/avx512

@ghost

Copy link
Copy Markdown

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

Issue Details

Overview

This PR implements an AVX512 code path for Base64 encoding/Decoding. This is based on the work by Wojciech Muła and Daniel Lemire. There is a fast AVX512VBMI path and the fallback uses AVX512F/BW - I'll refer to these as VBMI_AVAILABLE and VBMI_UNAVAILABLE here on. For performance purposes, this will be compared to an AVX2 implementation which will be referred to as BASE_Version
Reference for the algorithm:

This version uses intrinsics directly and not generic vector libraries due to lack of current support in JIt/Vector libraries to produce optimal code. Some additional support which would be required in order to use generic vector library for implementing this would be

  1. Add ShuffleUnsafe for Vector512
  2. Extend Vector512.Shuffle() to lower to intrinsics instead of going to fallback for more cases.
  3. Expand Vector512 surface area to incorporate more high level functions

Even the current implementation can be further optimized by adding the multishift() implementation. This is a further optimization

Generated code

(Will be focusing on the actual encoding/decoding code within the loop only)

Encoding

VBMI_AVAILABLE

image

VBMI_UNAVAILABLE

image

BASE_VERSION
image

Decoding

VBMI_AVAILABLE

image

VBMI_UNAVAILABLE

image

BASE_VERSION
image

Performance

ON ICX -

BASE_VERSION vs VBMI_UNAVAILABLE

image

BASE_VERSION vs VBMI_AVAILABLE
image

Author:DeepakRajendrakumaran
Assignees:-
Labels:

area-System.Buffers, community-contribution, needs-area-label

Milestone:-

@DeepakRajendrakumaran

Copy link
Copy Markdown
ContributorAuthor

I am not an expert in THIRD-PARTY-NOTICES.TXT 🙂 but seems like the link to that article is worth adding here https://github.com/dotnet/runtime/blob/main/THIRD-PARTY-NOTICES.TXT#L345

There is an AVX512 based implementation in there - https://github.com/aklomp/base64/tree/master/lib/arch/avx512.

Do we use any of the code from that repo? I see it has BSD-2 license

Not directly but the logic(including shuffle constants are similar). But this implementation uses '_mm512_multishift_epi64_epi8' and that's not the one I'm using. This(https://github.com/WojciechMula/base64simd/blob/master/encode/encode.avx512vbmi.cpp) in particular is probably worth mentioning in hindsight(Since I used the non multishift version in my implementation with VBMI)

I used the below as resources to understand available implementations and available options(But they are all related). Which brings up the question which of these exactly I should be referencing

esp this for understanding : http://0x80.pl/notesen/2016-04-03-avx512-base64.html#id29

https://github.com/WojciechMula/base64simd/tree/masterhttps://arxiv.org/pdf/1910.05109.pdfhttps://github.com/lemire/fastbase64/blob/master/src/fastavx512bwbase64.chttps://github.com/aklomp/base64/tree/master/lib/arch/avx512

@EgorBo I modified the reference to point to https://github.com/WojciechMula/base64simd/tree/master. Which has the closest versions to the implementation I went with. Will this require me adding anything to notice?

@DeepakRajendrakumaran

Copy link
Copy Markdown
ContributorAuthor

I am not an expert in THIRD-PARTY-NOTICES.TXT 🙂 but seems like the link to that article is worth adding here https://github.com/dotnet/runtime/blob/main/THIRD-PARTY-NOTICES.TXT#L345

There is an AVX512 based implementation in there - https://github.com/aklomp/base64/tree/master/lib/arch/avx512.

Do we use any of the code from that repo? I see it has BSD-2 license

Not directly but the logic(including shuffle constants are similar). But this implementation uses '_mm512_multishift_epi64_epi8' and that's not the one I'm using. This(https://github.com/WojciechMula/base64simd/blob/master/encode/encode.avx512vbmi.cpp) in particular is probably worth mentioning in hindsight(Since I used the non multishift version in my implementation with VBMI)
I used the below as resources to understand available implementations and available options(But they are all related). Which brings up the question which of these exactly I should be referencing
esp this for understanding : http://0x80.pl/notesen/2016-04-03-avx512-base64.html#id29
https://github.com/WojciechMula/base64simd/tree/masterhttps://arxiv.org/pdf/1910.05109.pdfhttps://github.com/lemire/fastbase64/blob/master/src/fastavx512bwbase64.chttps://github.com/aklomp/base64/tree/master/lib/arch/avx512

@EgorBo I modified the reference to point to https://github.com/WojciechMula/base64simd/tree/master. Which has the closest versions to the implementation I went with. Will this require me adding anything to notice?

Have updated THIRD PARTY NOTICE based on conversation with @tannergooding . Removing fallback avx512Bw path meant I had to add only 2 references.

@EgorBoEgorBo left a comment

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.

Thanks! Looks way simpler now

@BruceForstallBruceForstall added avx512 Related to the AVX-512 architecture and removed needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners labels Sep 25, 2023
@BruceForstallBruceForstall added this to the 9.0.0 milestone Sep 25, 2023
@DeepakRajendrakumaran

Copy link
Copy Markdown
ContributorAuthor

@tannergooding@BruceForstall Any comments on this? I'd be great if we can move this forward this week,

@BruceForstall

Copy link
Copy Markdown
Contributor

I'm not the right person to review this. If @tannergooding can't review, maybe @stephentoub can review (or pick an appropriate reviewer).

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.

This comment isn't quite accurate.

Vector512.IsHardwareAccelerated can be made to return true for Skylake-X and up to before IceLake via an environment variable. This is why the caller has the check for Vector512.IsHardwareAccelerated && Avx512Vbmi.IsSupported and why this function has [CompExactlyDependsOn(typeof(Avx512Vbmi))]

We're fine with it not being usable pre IceLake since those often incur heavier downclocking and its unnecessary complexity for a non-default scenario.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Removed line 667

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: Most other places in the JIT we do str.Store(dest) since its an extension method and can be accessed using instance syntax.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

I'm not sure I fully understand how this works

image

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.

It's likely conflicting because dest is a byte* while str is a Vector512<sbyte> and so it can't resolve

str.Store((sbyte*)dest) should fix it, or str.AsByte().Store(dest). The former is less IL, most notably.

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Ah..I messed up and was using str.AsSbyte().Store(dest) It's fixed now. Thank you

@tannergoodingtannergooding left a comment

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.

LGTM. Just a request to cleanup a couple minor things.

@DeepakRajendrakumaran
DeepakRajendrakumaranforce-pushed the encoding branch 2 times, most recently from 4b2f7d1 to fc05bebCompareOctober 24, 2023 20:28
@DeepakRajendrakumaran

Copy link
Copy Markdown
ContributorAuthor

LGTM. Just a request to cleanup a couple minor things.

I've committed the clean-up changes. Please let me know if you want me to make any other changes

@tannergooding
tannergooding merged commit 9ad24ae into dotnet:mainOct 25, 2023
liveans pushed a commit to liveans/dotnet-runtime that referenced this pull request Nov 9, 2023
* Adding AVX512 path to Base64 encoding/Decoding
* Addressing review Comments.
Signed-off-by: Deepak Rajendrakumaran <deepak.rajendrakumaran@intel.com>
* Removing fallback path.
* Updating Third Party Notice.
* Addressing review comments
---------
Signed-off-by: Deepak Rajendrakumaran <deepak.rajendrakumaran@intel.com>
@ghostghost locked as resolved and limited conversation to collaborators Nov 24, 2023
@DeepakRajendrakumaran
DeepakRajendrakumaran deleted the encoding branch August 3, 2026 23:43
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Buffersavx512Related to the AVX-512 architecturecommunity-contributionIndicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants

@DeepakRajendrakumaran@danmoseley@EgorBo@BruceForstall@tannergooding@MihaZupan@marek-safar