我目前正在试验GCC 矢量扩展。但是,我想知道如何sqrt(vec)
按预期工作。
如:
typedef double v4d __attribute__ ((vector_size (16)));
v4d myfunc(v4d in)
{
return some_sqrt(in);
}
并且至少在最近的 x86 系统上,它会发出对相关固有 sqrtpd 的调用。是否有适用于矢量类型的 sqrt 内置 GCC,或者是否需要降级到内在级别才能完成此操作?
我目前正在试验GCC 矢量扩展。但是,我想知道如何sqrt(vec)
按预期工作。
如:
typedef double v4d __attribute__ ((vector_size (16)));
v4d myfunc(v4d in)
{
return some_sqrt(in);
}
并且至少在最近的 x86 系统上,它会发出对相关固有 sqrtpd 的调用。是否有适用于矢量类型的 sqrt 内置 GCC,或者是否需要降级到内在级别才能完成此操作?
看起来这是一个错误: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];
}
您还可以尝试使用与矢量扩展分开的自动矢量化来碰碰运气。
我对这个问题的解读是,您想要 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 和 x86-64 clang 10.0.1
使用-O3 -march=skylake
:
myfunc:
vsqrtpd %ymm0, %ymm0 # (or just `ymm0` for Intel syntax)
ret
ymm0
是返回值寄存器。
也就是说,碰巧有一个内置的: __builtin_ia32_sqrtpd256
,它不需要内在的标头。但是,我肯定会阻止它的使用。
您可以直接遍历向量
#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 避免这些,则生成简单sqrtpd
的 .
https://godbolt.org/g/aCuovX
GCC 可能有一个错误,因为即使只有 2 个元素才能获得最佳代码,我也必须循环到 4。
但是对于 AVX 和 AVX512,GCC 和 Clang 是理想的
AVX https://godbolt.org/g/qdTxyp
AVX512 https://godbolt.org/g/MJP1n7