【问题标题】:GCC Vector Extensions SqrtGCC 向量扩展 Sqrt
【发布时间】:2013-09-26 02:15:58
【问题描述】:

我目前正在试验GCC vector extensions。但是,我想知道如何让sqrt(vec) 按预期工作。

如:

typedef double v4d __attribute__ ((vector_size (16)));
v4d myfunc(v4d in)
{
    return some_sqrt(in);
}

至少在最近的 x86 系统上,它会发出对相关固有 sqrtpd 的调用。是否有适用于矢量类型的 sqrt 内置 GCC,或者是否需要降级到内在级别才能完成此操作?

【问题讨论】:

  • 就像处理数组一样。
  • 考虑到有一条 ISA 指令专门设计用于对根向量进行平方运算,其速度可能是两个标量平方根的两倍,所以这有点不理想。
  • 看起来这是一个错误:gcc.gnu.org/bugzilla/show_bug.cgi?id=54408 除了按组件进行之外,我不知道任何解决方法。无论如何,向量扩展从来都不是要替换特定于平台的内在函数。
  • 作为答案发布,我非常乐意接受它作为解决方案。

标签: gcc vectorization


【解决方案1】:

看起来这是一个错误:http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54408 除了按组件进行之外,我不知道任何解决方法。无论如何,向量扩展从来都不是要替换特定于平台的内在函数。

为此效果的一些时髦代码:

#include <cmath>

#include <utility>

template <::std::size_t...> struct indices { };

template <::std::size_t M, ::std::size_t... Is>
struct make_indices : make_indices<M - 1, M - 1, Is...> {};

template <::std::size_t... Is>
struct make_indices<0, Is...> : indices<Is...> {};

typedef float vec_type __attribute__ ((vector_size(4 * sizeof(float))));

template <::std::size_t ...Is>
vec_type sqrt_(vec_type const& v, indices<Is...> const)
{
  vec_type r;

  ::std::initializer_list<int>{(r[Is] = ::std::sqrt(v[Is]), 0)...};

  return r;
}

vec_type sqrt(vec_type const& v)
{
  return sqrt_(v, make_indices<4>());
}

int main()
{
  vec_type v;

  return sqrt(v)[0];
}

您也可以试试自动矢量化,这与矢量扩展是分开的。

【讨论】:

    【解决方案2】:

    你可以直接遍历向量

    #include <math.h>
    typedef double v2d __attribute__ ((vector_size (16)));   
    v2d myfunc(v2d in) {
        v2d out;
        for(int i=0; i<2; i++) out[i] = sqrt(in[i]);
        return out;
    }
    

    sqrt 函数必须捕获带符号的零和 NAN,但如果您使用 -Ofast 避免这些,Clang 和 GCC 都只会生成 sqrtpdhttps://godbolt.org/g/aCuovX

    GCC 可能存在错误,因为即使只有 2 个元素才能获得最佳代码,我也必须循环到 4。

    但是对于 AVX 和 AVX512,GCC 和 Clang 是理想的

    AVX https://godbolt.org/g/qdTxyp

    AVX512 https://godbolt.org/g/MJP1n7

    【讨论】:

    【解决方案3】:

    我对这个问题的解读是,您想要 4 个压缩双精度值的平方根……那是 32 字节。使用适当的 AVX 内在函数:

    #include <x86intrin.h>
    
    typedef double v4d __attribute__ ((vector_size (32)));
    v4d myfunc (v4d v) {
        return _mm256_sqrt_pd(v);
    }
    

    x86-64 gcc 10.2 and x86-64 clang 10.0.1 使用-O3 -march=skylake

    myfunc:
      vsqrtpd %ymm0, %ymm0 # (or just `ymm0` for Intel syntax)
      ret
    

    ymm0是返回值寄存器。

    也就是说,碰巧有一个内置函数:__builtin_ia32_sqrtpd256,它不需要内在函数标头。但是,我绝对不鼓励使用它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-03-08
      • 2021-04-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多