Выбор индекса constexpr из динамического индекса - PullRequest
0 голосов
/ 25 мая 2019

У меня есть код C ++, который вызывает некоторые функции SSE / AVX, принимающие немедленные значения индекса (например, int _mm_extract_epi16 (__m128i a, int imm8)). Проблема в том, что я не знаю значение индекса во время компиляции, поэтому мне нужно выполнить динамическое преобразование int в constexpr int:

template <int index>
auto extract(__m128i a) noexcept
{
    static_assert(index < 8, "index must be less than 8");
    return _mm_extract_epi16(a, index);
}

auto extract(const __m128i a, const int index) noexcept
{
    switch (index) {
        case 0:  return extract<0>(a);
        case 1:  return extract<1>(a);
        case 2:  return extract<2>(a);
        case 3:  return extract<3>(a);
        case 4:  return extract<4>(a);
        case 5:  return extract<5>(a);
        case 6:  return extract<6>(a);
        case 7:  return extract<7>(a);
        default: return extract<7>(a);
    }
}

Я обновляю свою кодовую базу до AVX2 и AVX-512 (и, следовательно, увеличиваю количество дел до 16 и 32 соответственно), и начал задаваться вопросом, есть ли лучший способ сделать это? Или, по крайней мере, таким образом, чтобы избежать печатания?

1 Ответ

3 голосов
/ 25 мая 2019
template <std::size_t... Is>
auto extract(const __m128i a, const int index, std::index_sequence<Is...>) noexcept
{
    if(index < 8 && index >= 0)
    {
        decltype(extract<0>(a)) r;
        int unused[] = {(index == Is ? (r = extract<Is>(a), 0) : 0)...};
        (void)unused;
        return r;
    }
    else
        return extract<7>(a);
}

auto extract(const __m128i a, const int index) noexcept
{
    return extract(a, index, std::make_index_sequence<8>{});
}

Или вместо этого вы можете использовать выражения сгиба в C ++ 17.Это скомпилируется в то же самое как переключатель.

Я бы, однако, утверждал, что в этом случае, поскольку все, что вы сохраняете, - это некоторая печать, просто копирование и вставка были бы в порядке.Проще читать и писать.

...