C++ SSE类型的pow

C++ SSE类型的pow,c++,c,sse,pow,C++,C,Sse,Pow,我使用SSE类型进行一些明确的矢量化计算,例如\uuUm128(在xmmintrin.h等中定义),但现在我需要将向量的所有元素提升到某个(相同)幂,即理想情况下,我想要类似\uUm128\uMM\uPow\uPS(\uUuUm128,float)的东西,不幸的是不存在 最好的解决办法是什么?我可以存储向量,在每个元素上调用std::pow,然后重新加载它。这是我能做的最好的了吗?当自动向量化本来可以很好地向量化的代码时,编译器如何实现对std::pow的调用?有没有提供有用信息的图书馆 (请注

我使用SSE类型进行一些明确的矢量化计算,例如
\uuUm128
(在
xmmintrin.h
等中定义),但现在我需要将向量的所有元素提升到某个(相同)幂,即理想情况下,我想要类似
\uUm128\uMM\uPow\uPS(\uUuUm128,float)
的东西,不幸的是不存在

最好的解决办法是什么?我可以存储向量,在每个元素上调用
std::pow
,然后重新加载它。这是我能做的最好的了吗?当自动向量化本来可以很好地向量化的代码时,编译器如何实现对std::pow的调用?有没有提供有用信息的图书馆

(请注意,这不是重复的,肯定没有有用的答案。)

对于
pow(x,y)
exp()
log()
的SSE实现,使用公式
exp(y*log(x))

编辑人@:
以上仅适用于
x
y
均为正值的情况。否则就需要更仔细的数学。请参阅。

对于这些类型的操作,我确实建议使用英特尔短向量数学库。该库与要支持的编译器列表中提到的英特尔编译器捆绑在一起。我怀疑它对gcc和clang是否有用,但它可以作为基准测试的参考点,无论您在哪里提出pow实现


从浮点值中生成一个向量

 _mm_pow_ps(v,_mm_ps1(f))

ssemath库的AVX版本现已提供:

使用该库,您可以使用:

exp256_ps(y*log256_ps(x)); // for pow(x, y)

当自动矢量化不是一个选项时,我使用了
exp/log
并将
pow(x,k)
写成
exp(k*log(x)
。不确定它与自动矢量化代码相比如何。你可以使用Agner Fog的矢量类。他有SIMD数学函数(包括pow,exp,log,sin,…)用于SSE、AVX和AVX512的单精度、浮点型和整数。我看不出有什么好的理由再使用英特尔的SVML或AMD的libm了。@Zboson,有没有好的C库用于
exp()
支持SSE4吗?我看了一下这个库。它看起来只限于gcc,只知道SSE2,代码中的文档很差。我还希望它用于AVX类型
\uuuuuuM256
\uuuM256d`。@Walter与MSVC配合得很好(注意链接底部的VS2010基准测试),代码变得更加清晰,当看到这似乎是主要的灵感。我需要它与gcc,icc,clang一起工作。原始的cephes库很棒!如果没有更好的,我至少可以实现我自己的日志和exp沿着这些库的路线。@Walter你有没有尝试编译我链接的库?大约有5个compiler特定的行,它们应该与您提到的所有编译器一起工作。抱歉,在过去几天中还有其他事情要做。但是这个库不支持我需要的所有向量类型。没有
\u mm\u pow\ps()
,恐怕。否则,我没有问。啊,我误解了这个问题。泰勒级数是传统的,正如前面提到的,是一个很好的资源。根据精确度的重要性,你可以使术语的数量更低。SVML对gcc很有用。
gcc-mveclibabi=SVML
甚至可以让向量器创建对vmlsPow4的调用这就是。@marglisse,
gcc
是否包含内置的英特尔SVML?gcc不包含SVML,它只知道如何生成对它的调用,如果您保证它可用于链接的话。是的,这些函数使用AVX为8
float
s提供log、exp、sin、cos和sincos函数。不幸的是,对应的ng
double
版本仍然很优秀(我现在确实需要更多)。您可以尝试使用Intel SPMD编译器:文档中说它支持pow和AVX