Я хочу задать вопрос о SIMD. Я не получаю AVX512
в своем ЦП, но хочу иметь _mm256_max_epu64.
Как мы можем реализовать эту функцию с помощью AVX2
?
Здесь я пытаюсь иметь свой тривиальный. Может быть, мы можем позволить этому быть обсуждением и улучшить это.
#define SIMD_INLINE inline __attribute__ ((always_inline))
SIMD_INLINE __m256i __my_mm256_max_epu64_(__m256i a, __m256i b) {
uint64_t *val_a = (uint64_t*) &a;
uint64_t *val_b = (uint64_t*) &b;
uint64_t e[4];
for (size_t i = 0; i < 4; ++i) e[i] = (*(val_a + i) > *(val_b + i)) ? *(val_a + i) : *(val_b + i);
return _mm256_set_epi64x(e[3], e[2], e[1], e[0]);
}
ИЗМЕНИТЬ как резюме:
Мы обсуждали __mm256
сравнение без знака. Я привел свою тривиальную реализацию выше, просто следуя самой базовой концепции: один __m256i
просто эквивалентен 4 uint64_t
или 4 float
, которые вместе составляют 256 бит.
Затем у нас был ответ от @chtz, который имеет больше смысла AVX
при вызове большего количества функций битового программирования из AVX
.
В итоге оказывается, что эти две реализации приводят к одной и той же сборке благодаря CLang
. Пример сборки из компилятора Explorer
Еще один _mm256_min_epu64_
добавил. Это просто отражение _mm256_max_epu64_
выше. Облегчить поиск для будущего использования.
SIMD_INLINE __m256i __my_mm256_min_epu64_(__m256i a, __m256i b) {
uint64_t *val_a = (uint64_t*) &a;
uint64_t *val_b = (uint64_t*) &b;
uint64_t e[4];
for (size_t i = 0; i < 4; ++i) e[i] = (*(val_a + i) < *(val_b + i)) ? *(val_a + i) : *(val_b + i);
return _mm256_set_epi64x(e[3], e[2], e[1], e[0]);
}