【问题标题】:Selecting a constexpr index from a dynamic index从动态索引中选择 constexpr 索引
【发布时间】:2019-10-11 16:38:16
【问题描述】:

我有调用一些 SSE/AVX 函数的 C++ 代码,这些函数采用立即索引值(例如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),并开始想知道是否有更好的方法来做到这一点?或者至少是一种避免大量输入的方法?

【问题讨论】:

    标签: c++ c++11 c++14 constexpr


    【解决方案1】:
    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 中使用折叠表达式。这编译为same thing 作为开关。

    然而,我认为在这种情况下,由于您所保存的只是一些打字,因此只需复制和粘贴就可以了。读写更简单。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-11-13
      • 2018-05-06
      • 1970-01-01
      • 2021-10-24
      • 1970-01-01
      相关资源
      最近更新 更多