【问题标题】:Computing x^y with GCC vector intrinsics使用 GCC 向量内在函数计算 x^y
【发布时间】:2012-11-05 15:54:48
【问题描述】:

假设我有一个 2 元素向量定义如下(使用 GCC 语法打包向量)

// packed vector of 2-elements
typedef double v2d __attribute__((vector_size(sizeof(double)*2)));

v2d x = ...;
double y = ...;

x[0] = pow(x[0], y)
x[1] = pow(x[1], y)

我想知道是否有更快的方法来使用向量运算进行两次幂计算。架构是 x86-64 上的 GCC,平台特定的代码是可以的。

【问题讨论】:

  • 实现一个通用的幂函数很困难,因为你可能需要exp()log()。可能有太多的分支无法通过矢量化获得有价值的加速。但我只是在猜测。
  • 不,SIMD 指令集没有任何允许加速 pow() 的操作。 SSE2 只有 add、sub、mul、div、max、min 和 sqrt。甚至没有针对它的非矢量化指令。
  • 如果 "y" 被限制为 unsigned int 而不是 double,可能会有一些希望。实际上,使用经典的“移位和乘法”算法,可以并行评估两个向量的元素。只是我的猜测。

标签: c performance optimization gcc sse


【解决方案1】:

您可以直接循环元素,并使用正确的选项 GCC 和 ICC 将使用矢量化 pow 函数

#include <math.h>
typedef double vnd __attribute__((vector_size(sizeof(double)*2)));

vnd foo(vnd x, vnd y) {
    #pragma omp simd
    for(int i=0; i<2; i++) x[i] = pow(x[i], y[i]); 
    return x;
}

仅使用-O2,ICC 仅生成call __svml_pow2SVML(短向量数学库)是英特尔的向量化数学库。 With -Ofast -fopenmp GCC 只生成 call _ZGVbN2vv___pow_finite

Clang 不会对其进行矢量化。

https://godbolt.org/g/pjpzFX

【讨论】:

    【解决方案2】:

    是的,如果您没有特殊情况(负数、0、1、NaN 等),这应该是可能的,因此代码路径是线性的。

    Here 是 IEEE754 双精度的pow 函数的通用代码,它没有循环结构,所以如果你充实所有特殊情况,向量化似乎很简单。玩得开心。

    【讨论】:

    • 哈哈...我明白你所说的“玩得开心”是什么意思。 :)
    猜你喜欢
    • 1970-01-01
    • 2012-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多