Repository navigation
Use vpermd for AVX2 dynamic 32/64-bit swizzle - #1446
Conversation
|
Can you remove Claude as co author? I am okay with Assisted by AI. As a marker at least it does not pollute the stats :) |
eca94e5 to
63c540c
Compare
| XSIMD_SWIZZLE_PATTERN_CASE(OddThenEven); | ||
| XSIMD_SWIZZLE_PATTERN_CASE(InterleavePairs); | ||
| // Runtime index vectors with duplicates: | ||
| SUBCASE("dynamic_duplicates") { swizzle_test<B>().dynamic_duplicates(); } |
There was a problem hiding this comment.
use the macro above for consistency
There was a problem hiding this comment.
Emm this is a subcase and didn't calls xsimd::fill_pattern 🤔, so should we just leave subcase? This just verify the case for duplicate, which is mentioned eariler
| { | ||
| std::size_t count = 1; | ||
| for (std::size_t i = 0; i < N; ++i) | ||
| count *= N; |
There was a problem hiding this comment.
that's std::accumulate, but you could also use the direct formula
|
I've a naive question, I just use |
63c540c to
a12dbdd
Compare
|
can we add a test for out of range? |
| XSIMD_INLINE batch<T, A> swizzle(batch<T, A> const& self, batch<uint64_t, A> const& mask, requires_arch<avx2>) noexcept | ||
| { | ||
| // A 64 bits index i selects the 32 bits pair (2i, 2i + 1). | ||
| __m256i lo = _mm256_castps_si256(_mm256_moveldup_ps(_mm256_castsi256_ps(mask))); |
There was a problem hiding this comment.
I am not a fan of this triple cast + sum:
how about: _mm256_shuffle_epi32(mask, _MM_SHUFFLE(2, 2, 0, 0)) + _mm256_setr_epi32(0, 1, 0, 1, 0, 1, 0, 1)
There was a problem hiding this comment.
--- a/include/xsimd/arch/xsimd_avx2.hpp
+++ b/include/xsimd/arch/xsimd_avx2.hpp
@@ -1314,8 +1314,8 @@ namespace xsimd
XSIMD_INLINE batch<T, A> swizzle(batch<T, A> const& self, batch<uint64_t, A> const& mask, requires_arch<avx2>) noexcept
{
// A 64 bits index i selects the 32 bits pair (2i, 2i + 1).
- __m256i lo = _mm256_castps_si256(_mm256_moveldup_ps(_mm256_castsi256_ps(mask)));
- __m256i idx = _mm256_add_epi32(_mm256_add_epi32(lo, lo), _mm256_set1_epi64x(int64_t(1) << 32));
+ __m256i lo = _mm256_shuffle_epi32(mask, _MM_SHUFFLE(2, 2, 0, 0));
+ __m256i idx = _mm256_add_epi32(_mm256_add_epi32(lo, lo), _mm256_setr_epi32(0, 1, 0, 1, 0, 1, 0, 1));
return _mm256_permutevar8x32_epi32(self, idx);
}
I am not sure about what is the general rule. I personally think of masking as a boolean. Wheter is a simple simd register or boolean or the single bits in an integer. I think of indices when I am doing a swizzle type operation where the numbers are integer not just booleans. But, it is not a general rule. As long as it is clear anything is fine. The golden rule of naming I guess is answering the questions What is that?! |
56011b2 to
ba6533d
Compare
DiamonDinoia
left a comment
There was a problem hiding this comment.
One simplification of the tests then good to go.
PR xtensor-stack#1141 routed the AVX2 dynamic 32/64-bit swizzle to the AVX fallback (vperm2f128 + 2x vpermilps + blendv), on the assumption that vpermps does not accept repeated indices. Both the Intel SDM and the AMD APM state that it does, and the constant-mask variant already went back to vpermd in xtensor-stack#1201. Restore the single-instruction lowering for the dynamic indices too: - 32-bit: one vpermps / vpermd instead of 7 instructions - 64-bit: widen index i to the pair (2i, 2i + 1) with vpshufd + add, then vpermd: 4 instructions instead of 11 Out-of-range indices keep wrapping modulo the batch size, as before. Add a swizzle test with runtime index vectors that repeat lanes: every single-lane broadcast and deterministic mt19937 patterns. Fixes xtensor-stack#1445
ba6533d to
eb3869d
Compare
#1141 routed the AVX2 dynamic 32/64-bit swizzle to the AVX fallback (vperm2f128 + 2x vpermilps + blendv), on the assumption that vpermps does not accept repeated indices. Both the Intel SDM and the AMD APM state that it does, and the constant-mask variant already went back to vpermd in #1201. Restore the single-instruction lowering for the dynamic mask too:
then vpermd: 4 instructions instead of 11
Out-of-range indices keep wrapping modulo the batch size, as before.
Add a swizzle test with runtime index vectors that repeat lanes: every single-lane broadcast, all N^N patterns when N <= 4, and pseudo-random patterns otherwise.
Fixes #1445