Автоматическая векторизация в Visual Studio 2012 express на std :: vector не происходит

У меня есть простая программа, в которой у меня есть 3 std :: vector и использую их для циклов. После включения флага компиляции я проверяю, оптимизированы ли эти циклы или нет. Но 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> — Анализирующая функция: главная
2> d: \ test \ ssetestonvectors \ main.cpp (12): информация C5002: цикл не векторизован по причине ‘1200’
2> d: \ test \ ssetestonvectors \ main.cpp (18): информация C5002: цикл не векторизован по причине ‘1200’

Когда я прочитал о коде ошибки 1200 на странице MSDN:
https://msdn.microsoft.com/en-us/library/jj658585.aspx
Он указывает, что код ошибки 1200 вызван тем, что «Loop содержит зависимость, переносимую циклом»

Я не могу понять, как этот цикл содержит это. У меня есть какой-то код, который мне нужно оптимизировать, чтобы он мог использовать функцию автоматической векторизации Visual Studio, чтобы его можно было оптимизировать для SSE2. Этот код содержит векторные операции. Поэтому я не могу этого сделать, потому что каждый раз, когда visual studio показывает какой-то код ошибки, подобный этому.

1

Решение

Я думаю, что ваша проблема заключается в том, что:

    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 ++.

редактировать: ФП уточнил, что замена звонков на operator[] с призывом к at выдает другое сообщение об ошибке (хотя это может быть быть потому что at является более сложным).

Если проблема не в вызовах функций, моя следующая гипотеза состоит в том, что operator [] сводится к чему-то вроде return this.__begin[i]; и векторизатор не знает, что отличается std::vectorс неперекрывающейся памятью. Если это так, окончательный блок кода остается решением.

2

Другие решения

Автовекторизация — довольно новая функция MSVC, и вы используете более старую версию MSVC. Так что это далеко от совершенства. Microsoft знает это, поэтому они решили векторизовать код только тогда, когда он абсолютно безопасен.

Конкретное сообщение об ошибке немного кратко. На самом деле это должно сказать «петля может быть содержать зависимость от переноса данных «. Так как MSVC не может доказать их отсутствие, он не векторизируется.

2