【问题标题】:For loop over vector vectorized using C style pointers but not using iteratorsFor 循环使用 C 样式指针向量化的向量,但不使用迭代器
【发布时间】:2017-01-23 21:16:12
【问题描述】:

我编写了一小段代码,用于累积比 std::accumulate 更快的向量值,因为它允许对函数进行向量化。该函数的主要前提是该向量在累加后不再使用。代码如下:

template <typename floatType>
template <typename Iterator>
double Numeric_class<floatType>::AmDestructiveAccumulate(Iterator A, size_t length)
{
    if (length == 1)
    {
        return A[0];
    }

    Iterator temp_;
    while (length > 1)
    {
        if (length & 1) // odd
        {
            A[0] += A[length - 1]; // We add the last value which would otherwise be lost.
            length >>= 1;
            temp_ = A+length;
            for (int i = 0; i < length; i++)
            {
                A[i] += temp_[i];
            }
        }
        else // even
        {
            length >>= 1;
            temp_ = A+length;
            for (int i = 0; i < length; i++)
            {
                A[i] += temp_[i];
            }
        }
    }
    return A[0];
}

该函数基本上将向量分成两半,并取两半的成对和。在此之后,它将前半部分的总和分成两个等长的范围,然后再次成对地求和,依此类推。

我将此功能与std::vector&lt;double&gt; data 一起使用。如果我用 A 调用它是 data.data()。矢量化故事按预期进行,我的执行速度也显着提高。如果我使用 data.begin(),则不会发生矢量化。我使用 VC2015 编译了代码并进行了全面优化。是否有理由说明对代码的迭代器版本进行矢量化是非法的,或者 VC 只是不这样做,尽管它是合法的。

【问题讨论】:

  • TBH 这听起来像是一个可怕的算法,令人印象深刻的是优化器设法挽救了至少一些版本。您将线性访问 O(N) 算法变成了具有非线性访问的 O(N log N) 变体。
  • @MSalters 这是不正确的。访问仍然是 O(N)。它是 N+N/2+N/4+N/8 .... 这个几何级数收敛到 N*2。此外,访问在每次迭代中都是线性的。最后但同样重要的是:分析显示相关 N 的性能有所提高。
  • 公平点,它看起来像两个长度为 N/2 的内循环,用于奇数和偶数,但只使用了两个中的一个,因此它不是 N+2*(N/2)+4*(N/4)+...
  • gcc 为两个版本生成几乎相同的目标代码。 VS2015 产生了相当不同的目标文件,但并没有那么离谱,我在这两种情况下都看到了矢量化指令。你可以在某个粘贴箱中发布这两个版本的程序集列表吗?

标签: c++ vector iterator vectorization


【解决方案1】:

核心问题将是A[i] += temp_[i];。请注意,Atemp 互为别名,但您在运行时选择的 [i] 意味着这只是理论上的。现在,[i] 究竟是什么意思?如果A 是一个指针,那只是*(A+i) 的简写,但是当A 是一个迭代器时,它就是一个函数调用。

高效的向量化要求编译器发现对A[i] 的写入不会影响对temp[i] 的后续读取,这是一个重要的观察结果。没有循环携带的依赖,但优化器必须能够证明它。

【讨论】:

  • 换句话说,迭代器的情况并没有什么不合法的地方,只是优化器很难理解它。说实话,对于双重情况​​,收益是相当小的。但是对于浮点数,向量单元同时处理 4 个值,效果大约是 2 倍。
  • @PaulR.:就我个人而言,我会把它写成使用 AVX 的老式线性加法。所有写信给A[ ] 的人都会受到伤害;对于这样一个简单的操作,您将受到带宽限制。
  • 听起来很有希望。我会检查一下。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-03-03
  • 1970-01-01
  • 1970-01-01
  • 2014-10-13
  • 1970-01-01
  • 1970-01-01
  • 2016-10-06
相关资源
最近更新 更多