对于使用C样式指针而不是使用迭代器

时间:2017-01-23 10:01:47

标签: c++ vector iterator vectorization

我编写了一小段代码,用于累积比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<double> data一起使用。如果我用A称为data.data()。矢量化故事按预期放置,我的执行速度也显着提高。如果我使用data.begin(),则不会进行矢量化。我使用VC2015编译了代码并进行了全面优化。有没有理由为什么对代码的迭代器版本进行矢量化是非法的,或者VC不会这样做,尽管它是合法的。

1 个答案:

答案 0 :(得分:2)

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

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