GCC Vector Extensions Sqrt

时间:2013-09-20 15:59:28

标签: gcc vectorization

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

如:

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

并且至少在最近的x86系统上它会发出对相关内在sqrtpd的调用。是否有一个内置于sqrt的GCC适用于矢量类型,还是需要下拉到内在级别来实现这一目标?

3 个答案:

答案 0 :(得分: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];
}

你也可以尝试使用自动矢量化,这与矢量扩展分开。

答案 1 :(得分:1)

您可以直接循环向量

#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可能有一个错误,因为我必须循环到4,即使只有2个元素可以获得最佳代码。

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

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

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

答案 2 :(得分:0)

我对这个问题的解读是你想要4个打包双精度值的平方根......即32个字节。使用适当的AVX内在:

#include <x86intrin.h>

typedef double v4d __attribute__ ((vector_size (32)));
v4d myfunc (v4d &in) {
    return _mm256_sqrt_pd(in);
}

使用-Ofast -march=skylakehttps://godbolt.org/g/QMbVVk

AT&amp; T语法:

myfunc(double __vector(4)&):
  vsqrtpd (%rdi), %ymm0
  ret

英特尔语法:

myfunc(double __vector(4)&):
  vsqrtpd ymm0, YMMWORD PTR [rdi]
  ret

YMM0是返回值寄存器 这个Q&amp; A已有几年的历史了。这是gcc-7.2和clang-5.0。

那就是,恰好有一个内置:__builtin_ia32_sqrtpd256,它不需要内在函数头。但我绝对不鼓励使用它。