Skip to content

Add SVE implementation of remove - #6407

Open
Hari Limaye (hazzlim) wants to merge 3 commits into
microsoft:mainfrom
hazzlim:remove-sve-pr-squash
Open

Add SVE implementation of remove#6407
Hari Limaye (hazzlim) wants to merge 3 commits into
microsoft:mainfrom
hazzlim:remove-sve-pr-squash

Conversation

@hazzlim

Copy link
Copy Markdown
Contributor

This PR adds an SVE implementation of remove.

Benchmark results (sizes/benchmarks for which the code path is unchanged are omitted):

Measured speedups on a Neoverse N2 Machine (Cobalt 100)

benchmark speedup
r<alg_type::std_fn, std::uint32_t>/7 0.999x
r<alg_type::std_fn, std::uint32_t>/15 0.997x
r<alg_type::std_fn, std::uint32_t>/31 1.169x
r<alg_type::std_fn, std::uint32_t>/47 1.173x
r<alg_type::std_fn, std::uint32_t>/63 1.243x
r<alg_type::std_fn, std::uint32_t>/95 1.343x
r<alg_type::std_fn, std::uint32_t>/127 1.378x
r<alg_type::std_fn, std::uint32_t>/255 1.488x
r<alg_type::std_fn, std::uint32_t>/511 1.525x
r<alg_type::std_fn, std::uint32_t>/1023 1.61x
r<alg_type::std_fn, std::uint32_t>/2047 1.607x
r<alg_type::std_fn, std::uint32_t>/4095 1.6x
r<alg_type::std_fn, std::uint32_t>/3230 1.608x
r<alg_type::std_fn, std::uint64_t>/7 1.007x
r<alg_type::std_fn, std::uint64_t>/15 1.002x
r<alg_type::std_fn, std::uint64_t>/31 1.019x
r<alg_type::std_fn, std::uint64_t>/47 1.017x
r<alg_type::std_fn, std::uint64_t>/63 1.129x
r<alg_type::std_fn, std::uint64_t>/95 1.197x
r<alg_type::std_fn, std::uint64_t>/127 1.174x
r<alg_type::std_fn, std::uint64_t>/255 1.216x
r<alg_type::std_fn, std::uint64_t>/511 1.186x
r<alg_type::std_fn, std::uint64_t>/1023 1.209x
r<alg_type::std_fn, std::uint64_t>/2047 1.209x
r<alg_type::std_fn, std::uint64_t>/4095 1.312x
r<alg_type::std_fn, std::uint64_t>/3230 1.307x
r<alg_type::rng, std::uint32_t>/7 1.007x
r<alg_type::rng, std::uint32_t>/15 0.997x
r<alg_type::rng, std::uint32_t>/31 1.096x
r<alg_type::rng, std::uint32_t>/47 1.12x
r<alg_type::rng, std::uint32_t>/63 1.203x
r<alg_type::rng, std::uint32_t>/95 1.35x
r<alg_type::rng, std::uint32_t>/127 1.38x
r<alg_type::rng, std::uint32_t>/255 1.486x
r<alg_type::rng, std::uint32_t>/511 1.537x
r<alg_type::rng, std::uint32_t>/1023 1.599x
r<alg_type::rng, std::uint32_t>/2047 1.603x
r<alg_type::rng, std::uint32_t>/4095 1.589x
r<alg_type::rng, std::uint32_t>/3230 1.574x
r<alg_type::rng, std::uint64_t>/7 1.005x
r<alg_type::rng, std::uint64_t>/15 1.003x
r<alg_type::rng, std::uint64_t>/31 1.028x
r<alg_type::rng, std::uint64_t>/47 1.005x
r<alg_type::rng, std::uint64_t>/63 1.084x
r<alg_type::rng, std::uint64_t>/95 1.153x
r<alg_type::rng, std::uint64_t>/127 1.164x
r<alg_type::rng, std::uint64_t>/255 1.204x
r<alg_type::rng, std::uint64_t>/511 1.241x
r<alg_type::rng, std::uint64_t>/1023 1.254x
r<alg_type::rng, std::uint64_t>/2047 1.225x
r<alg_type::rng, std::uint64_t>/4095 1.231x
r<alg_type::rng, std::uint64_t>/3230 1.243x
rc<alg_type::std_fn, std::uint8_t>/7 0.999x
rc<alg_type::std_fn, std::uint8_t>/15 0.998x
rc<alg_type::std_fn, std::uint8_t>/31 1.52x
rc<alg_type::std_fn, std::uint8_t>/47 1.426x
rc<alg_type::std_fn, std::uint8_t>/63 1.201x
rc<alg_type::std_fn, std::uint8_t>/95 1.068x
rc<alg_type::std_fn, std::uint16_t>/7 0.962x
rc<alg_type::std_fn, std::uint16_t>/15 1.469x
rc<alg_type::std_fn, std::uint16_t>/31 2.414x
rc<alg_type::std_fn, std::uint16_t>/47 2.217x
rc<alg_type::std_fn, std::uint16_t>/63 1.771x
rc<alg_type::std_fn, std::uint16_t>/95 1.624x
rc<alg_type::std_fn, std::uint16_t>/127 1.586x
rc<alg_type::std_fn, std::uint16_t>/255 1.139x
rc<alg_type::std_fn, std::uint16_t>/511 1.284x
rc<alg_type::std_fn, std::uint16_t>/1023 1.374x
rc<alg_type::std_fn, std::uint16_t>/2047 1.383x
rc<alg_type::std_fn, std::uint16_t>/4095 1.338x
rc<alg_type::std_fn, std::uint16_t>/3230 1.392x
rc<alg_type::std_fn, std::uint32_t>/7 1.073x
rc<alg_type::std_fn, std::uint32_t>/15 1.29x
rc<alg_type::std_fn, std::uint32_t>/31 1.528x
rc<alg_type::std_fn, std::uint32_t>/47 1.727x
rc<alg_type::std_fn, std::uint32_t>/63 1.826x
rc<alg_type::std_fn, std::uint32_t>/95 1.959x
rc<alg_type::std_fn, std::uint32_t>/127 1.971x
rc<alg_type::std_fn, std::uint32_t>/255 2.065x
rc<alg_type::std_fn, std::uint32_t>/511 2.06x
rc<alg_type::std_fn, std::uint32_t>/1023 2.086x
rc<alg_type::std_fn, std::uint32_t>/2047 2.111x
rc<alg_type::std_fn, std::uint32_t>/4095 2.095x
rc<alg_type::std_fn, std::uint32_t>/3230 2.142x
rc<alg_type::std_fn, std::uint64_t>/95 1x
rc<alg_type::std_fn, std::uint64_t>/127 0.998x
rc<alg_type::std_fn, std::uint64_t>/255 1.015x
rc<alg_type::std_fn, std::uint64_t>/511 1.008x
rc<alg_type::std_fn, std::uint64_t>/1023 1.015x
rc<alg_type::std_fn, std::uint64_t>/2047 1.008x
rc<alg_type::std_fn, std::uint64_t>/4095 1.002x
rc<alg_type::std_fn, std::uint64_t>/3230 1x
rc<alg_type::rng, std::uint8_t>/7 0.951x
rc<alg_type::rng, std::uint8_t>/15 1.296x
rc<alg_type::rng, std::uint8_t>/31 1.518x
rc<alg_type::rng, std::uint8_t>/47 1.391x
rc<alg_type::rng, std::uint8_t>/63 1.238x
rc<alg_type::rng, std::uint8_t>/95 1.084x
rc<alg_type::rng, std::uint16_t>/7 0.997x
rc<alg_type::rng, std::uint16_t>/15 1.442x
rc<alg_type::rng, std::uint16_t>/31 2.354x
rc<alg_type::rng, std::uint16_t>/47 2.061x
rc<alg_type::rng, std::uint16_t>/63 1.692x
rc<alg_type::rng, std::uint16_t>/95 1.514x
rc<alg_type::rng, std::uint16_t>/127 1.545x
rc<alg_type::rng, std::uint16_t>/255 1.133x
rc<alg_type::rng, std::uint16_t>/511 1.235x
rc<alg_type::rng, std::uint16_t>/1023 1.307x
rc<alg_type::rng, std::uint16_t>/2047 1.4x
rc<alg_type::rng, std::uint16_t>/4095 1.33x
rc<alg_type::rng, std::uint16_t>/3230 1.392x
rc<alg_type::rng, std::uint32_t>/7 1.038x
rc<alg_type::rng, std::uint32_t>/15 1.274x
rc<alg_type::rng, std::uint32_t>/31 1.573x
rc<alg_type::rng, std::uint32_t>/47 1.713x
rc<alg_type::rng, std::uint32_t>/63 1.797x
rc<alg_type::rng, std::uint32_t>/95 1.938x
rc<alg_type::rng, std::uint32_t>/127 1.977x
rc<alg_type::rng, std::uint32_t>/255 2.012x
rc<alg_type::rng, std::uint32_t>/511 2.06x
rc<alg_type::rng, std::uint32_t>/1023 2.088x
rc<alg_type::rng, std::uint32_t>/2047 2.097x
rc<alg_type::rng, std::uint32_t>/4095 2.089x
rc<alg_type::rng, std::uint32_t>/3230 2.089x
rc<alg_type::rng, std::uint64_t>/95 0.99x
rc<alg_type::rng, std::uint64_t>/127 0.996x
rc<alg_type::rng, std::uint64_t>/255 1.023x
rc<alg_type::rng, std::uint64_t>/511 1.015x
rc<alg_type::rng, std::uint64_t>/1023 1.014x
rc<alg_type::rng, std::uint64_t>/2047 1.024x
rc<alg_type::rng, std::uint64_t>/4095 1.014x
rc<alg_type::rng, std::uint64_t>/3230 1.007x

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).
There may be pipelines that require an authorized user to comment /azp run to run.

@BillyONeal

Copy link
Copy Markdown
Member

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 2 pipeline(s).

Comment thread stl/src/vector_algorithms.cpp Outdated
};

#if defined(_M_ARM64) // not ARM64EC, which lacks SVE
struct _SVE_8 {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We avoid macro-like names. _Sve_1 would be fine. Ditto below.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good point - done. It's just so drilled into me to use the "correct" (from an Arm branding perspective) capitalization of these things e.g. Neon not NEON and SVE not Sve 😄

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The NEON/Neon one is fun, because it used to be NEON and now it is Neon

#if !defined(_M_ARM64) && !defined(_M_ARM64EC)
#if defined(_M_ARM64) // not ARM64EC, which lacks SVE
const size_t _Size_bytes = _Byte_length(_First, _Last);
bool _Use_sve = _Use_FEAT_SVE() && (_Size_bytes > 512 || _Sve_vl() > 16);

@AlexGuteniev Alex Guteniev (AlexGuteniev) Aug 24, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Please explain _Size_bytes > 512 here in __std_remove_copy_8 as opposed to _Size_bytes <= 96 in __std_remove_copy_1, and just if (_Use_FEAT_SVE()) in __std_remove_copy_2 and __std_remove_copy_4

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I've added comments for __std_remove_copy_8 and __std_remove_copy_1.

I hope the if (_Use_FEAT_SVE()) conditions are self explanatory - the SVE is unconditionally faster.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Ah, I see, one SVE case competes against scalar, and the other against Neon, that makes sense then. thanks!

@StephanTLavavej Stephan T. Lavavej (StephanTLavavej) added performance Must go faster ARM64 Related to the ARM64 architecture labels Aug 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ARM64 Related to the ARM64 architecture performance Must go faster

Projects

Status: Initial Review

Development

Successfully merging this pull request may close these issues.

4 participants