1

我有一个简单的程序,其中我有 3 个 std::vector 并在 for 循环中使用它们。在启用编译标志后,我正在测试这些循环是否被优化。但是 Visual Studio 显示由于原因 1200,循环未矢量化。我的示例代码如下。

#include <iostream>
#include <vector>
#include <time.h>
int main(char *argv[], int argc)
{
    clock_t t=clock();
    int tempSize=100;
    std::vector<double> tempVec(tempSize);
    std::vector<double> tempVec1(tempSize);
    std::vector<double> tempVec2(tempSize);

    for(int i=0;i<tempSize;i++)
    {
        tempVec1[i] = 20;
        tempVec2[i] = 30;
    }

    for(int i=0,imax=tempSize;i<imax;i++)
        tempVec[i] = tempVec1[i] + tempVec2[i];

    t =clock()-t;          // stop the clock
    std::cout <<"Time in millisecs = " <<  t/double(CLOCKS_PER_SEC) <<      std::endl;
    return 0;
}

下面是使用启用选项“/Qvec-report:2”的代码编译的输出。

2> --- 分析函数:main 2> d:\test\ssetestonvectors\main.cpp(12) : info C5002: loop not vectorized due to reason '1200' 2> d:\test\ssetestonvectors\main.cpp( 18) : info C5002: loop not vectorized 由于原因“1200”

当我在 msdn 页面上阅读错误代码 1200 时: https ://msdn.microsoft.com/en-us/library/jj658585.aspx 它指定错误代码 1200 是由于“循环包含循环携带的数据依赖”

我无法理解这个循环是如何包含它的。我有一些需要优化的代码,以便它可以使用 Visual Studio 的自动矢量化功能,以便可以针对 SSE2 进行优化。此代码包含向量操作。所以我无法做到这一点,因为每次视觉工作室都会显示一些这样的错误代码。

4

2 回答 2

3

我认为你的问题是:

    for(int i=0,imax=tempSize;i<imax;i++)
        tempVec[i] = tempVec1[i] + tempVec2[i];

实际上

    for(int i=0,imax=tempSize;i<imax;i++)
        tempVec.operator[](i) = tempVec1.operator[](i) + tempVec2.operator[](i);

...并且矢量化器无法查看函数调用的内部情况。第一个解决方法是:

    const double* t1 = &tempVec1.front();
    const double* t2 = &tempVec2.front();
    double *t = &tempVec.front();
    for(int i=0,imax=tempSize;i<imax;i++)
        t[i] = t1[i] + t2[i];

问题在于矢量化器看不到 t、t1 和 t2 不重叠。您必须向编译器保证他们不会:

    const double* __restrict t1 = &tempVec1.front();
    const double* __restrict t2 = &tempVec2.front();
    double * __restrict t = &tempVec.front();
    for(int i=0,imax=tempSize;i<imax;i++)
        t[i] = t1[i] + t2[i];

显然(我希望)使用__restrict关键字(它不是标准 C++ 的一部分)意味着这段代码不能移植到其他 C++ 编译器。

编辑: OP 已经澄清,用调用替换调用operator[]at产生不同的失败消息(尽管这可能是因为at更复杂)。

如果问题不在于函数调用,我的下一个假设是operator []归结为类似return this.__begin[i];的东西,并且矢量化器不知道不同std::vector的 s 具有不重叠的内存。如果是这样,最终的代码块仍然是解决方案。

于 2016-10-17T07:02:15.860 回答
2

自动矢量化是 MSVC 的一项相当新的功能,您使用的是旧版本的 MSVC。所以它远非完美。微软知道这一点,所以他们决定只在绝对安全的情况下对代码进行矢量化。

特定的错误消息有点简洁。实际上,它应该说“循环可能包含循环携带的数据依赖”。由于 MSVC 无法证明它们不存在,因此它不会向量化。

于 2016-10-17T06:56:17.997 回答