#[non_exhaustive]pub enum Level {
Fallback(Fallback),
Sse4_2(Sse4_2),
Avx2(Avx2),
}Expand description
The level enum with the specific SIMD capabilities available.
The contained values serve as a proof that the associated target feature is available.
Variants (Non-exhaustive)§
This enum is marked as non-exhaustive
Fallback(Fallback)
Scalar fallback level, i.e. no supported SIMD features are to be used.
This can be created with [Level::fallback].
Sse4_2(Sse4_2)
The SSE4.2 instruction set on (32 and 64 bit) x86, plus popcnt and cmpxchg16b.
Also known as x86-64-v2.
All production CPUs with SSE4.2 also support the other two extensions, so it is safe to require them.
Avx2(Avx2)
The x86-64-v3 instruction set on (32 and 64 bit) x86, including AVX2 and FMA.
Implementations§
Source§impl Level
impl Level
Sourcepub fn new() -> Self
pub fn new() -> Self
Detect the available features on the current CPU, and returns the best level.
If no SIMD instruction set is available, a scalar fallback will be used instead.
This function requires the standard library, to use the
is_x86_feature_detected
or is_aarch64_feature_detected.
On wasm32, this requirement does not apply, so the standard library isn’t required.
Note that in most cases, this function should only be called by end-user applications.
Libraries should instead accept a Level argument, probably as they are
creating their data structures, then storing the level for any computations.
Libraries which wish to abstract away SIMD usage for their common-case clients,
should make their non-Level entrypoint match this function’s cfg; to instead
handle this at runtime, they can use try_detect,
handling the None case as they deem fit (probably panicking).
This strategy avoids users of the library inadvertently using the fallback level,
even if the requisite target features are available.
If you are on an embedded device where these macros are not supported, you should construct the relevant variants yourself, using whatever way your specific chip supports accessing the current level.
This value should be passed to dispatch!().
Sourcepub fn try_detect() -> Option<Self>
pub fn try_detect() -> Option<Self>
Get the target feature level suitable for this run.
Should be used in libraries if they wish to handle the case where
target features cannot be detected at runtime.
Most users should prefer new.
This is discussed in more detail in new’s documentation.
Sourcepub fn is_fallback(self) -> bool
pub fn is_fallback(self) -> bool
Check whether this is the Fallback level; that is, whether no better feature level could
be statically or dynamically detected. This is useful if there’s a scalarized version of
your algorithm that runs faster if SIMD isn’t supported.
This method is always available, even in cases where Fallback is not; for instance, if
you’re targeting a platform that always supports some level of SIMD. In such cases, it will
always return false.
Sourcepub fn as_sse4_2(self) -> Option<Sse4_2>
pub fn as_sse4_2(self) -> Option<Sse4_2>
If this is a proof that SSE4.2 (or better) is available, access that instruction set.
This method should be preferred over matching against the Sse4_2 variant of self,
because if Fearless SIMD gets support for an instruction set which is a superset of SSE4.2,
this method will return a value even if that “better” instruction set is available.
This can be used in combination with the safe_wrappers feature to gain checked access to
the level-specific SIMD capabilities.
Sourcepub fn as_avx2(self) -> Option<Avx2>
pub fn as_avx2(self) -> Option<Avx2>
If this is a proof that the x86-64-v3 feature set (or better) is available, access that instruction set.
This method should be preferred over matching against the AVX2 variant of self,
because if Fearless SIMD gets support for an instruction set which is a superset of AVX2,
this method will return a value even if that “better” instruction set is available.
This can be used in combination with the safe_wrappers feature to gain checked access to
the level-specific SIMD capabilities.
Sourcepub const fn baseline() -> Self
pub const fn baseline() -> Self
Get the strongest statically supported SIMD level.
That is, if your compilation run ambiently declares that a target feature is enabled,
this method will take that into account.
In most cases, you should use Level::new or Level::try_detect.
This method is mainly useful for libraries, where:
- Your crate features request that you not use the standard library, i.e. doesn’t enable
your
"std"crate feature reason (so you can’t useLevel::newandLevel::try_detectreturnsNone); AND - Your caller does not provide a
Level; AND - The library doesn’t want to panic when it can’t find a SIMD level.
Note that in these cases, the library should clearly inform the integrator
that it is using a fallback and so not getting optimal performance (e.g. by panicking if
debug_assertions are enabled, and emitting a log with the “error” level otherwise).
The messages given should also provide actionable fixes, such as pointing to the
entry-point which provides a Level, or your "std" feature.
Note that this is unaffected by the force-support-fallback feature.
Instead, you should use [Level::fallback] if you require the fallback level.
Sourcepub fn dispatch<W: WithSimd>(self, f: W) -> W::Output
pub fn dispatch<W: WithSimd>(self, f: W) -> W::Output
Dispatch f to a context where the target features which this Level proves are available are enabled.
Most users of Fearless SIMD should prefer to use dispatch!() to
explicitly vectorize a function. That has a better developer experience
than an implementation of WithSimd, and is less likely to miss a vectorization
opportunity.
This has two use cases:
- To call a manually written implementation of
WithSimd. - To ask the compiler to auto-vectorize scalar code.
For the second case to work, the provided function must be attributed with #[inline(always)].
Note also that any calls that function makes to other functions will likely not be auto-vectorized,
unless they are also #[inline(always)].