2015-05-08 4 views
13

Вот бесплатные функции, которые делают то же самое, но в первом случае цикл не векторизован, но в других случаях он есть. Почему это?Почему векторизация ведет себя по-разному почти для одного и того же кода?

#include <vector> 

typedef std::vector<double> Vec; 

void update(Vec& a, const Vec& b, double gamma) { 
    const size_t K = a.size(); 
    for (size_t i = 0; i < K; ++i) { // not vectorized 
     a[i] = b[i] * gamma - a[i]; 
    } 
} 

void update2(Vec& a, const Vec& b, double gamma) { 
    for (size_t i = 0; i < a.size(); ++i) { // vectorized 
     a[i] = b[i] * gamma - a[i]; 
    } 
} 

void update3(Vec& a, size_t K, const Vec& b, double gamma) { 
    for (size_t i = 0; i < K; ++i) { // vectorized 
     a[i] = b[i] * gamma - a[i]; 
    } 
} 

int main(int argc, const char* argv[]) { 
    Vec a(argc), b; 
    update(a, b, 0.5); 
    update2(a, b, 0.5); 
    update3(a, a.size(), b, 0.5); 
    return 0; 
} 

Соответствующие сообщения от компилятора (VS2013):

1> c:\home\dima\trws\trw_s-v1.3\trws\test\vector.cpp(7) : info C5002: loop not vectorized due to reason '1200' 
1> c:\home\dima\trws\trw_s-v1.3\trws\test\vector.cpp(13) : info C5001: loop vectorized 
1> c:\home\dima\trws\trw_s-v1.3\trws\test\vector.cpp(19) : info C5001: loop vectorized 

От комментариев по @tony

Причина 1200: «Цикл содержит зависимости по данным петлевых переносимым, которые предотвращают векторизации. Различные итерации петли мешают каждому другим, так что векторизация цикла приведет к неправильным ответам, а автоинтервализатор c аннота доказывает себе, что таких данных нет. зависимостей. " source

+2

Попробуйте другой компилятор? Другие (gcc и clang) делают векторизацию всех трех функций. –

+1

Что такое «причина 1200», зарегистрированная как? –

+1

Причина 1200: «Loop содержит зависящие от цикла данные, которые предотвращают векторизация. Различные итерации цикла мешают друг другу, так что векторизация цикла приводит к неправильным ответам, а автоинтервализатор не может доказать себе, что таких данных нет зависимости «. [источник] (https://msdn.microsoft.com/en-us/library/jj658585.aspx#BKMK_ReasonCode120x) – Tony

ответ

-3

Я думаю, что это происходит из-за многочисленный доступ к константному переменной K, который ограничивает назначение SIMD, как каждая команда имеет принести Конст переменным к

+2

Это явно не так. – harold

+0

Как насчет повторного доступа к неизменяемому K в третьей функции? Как насчет повторных вызовов 'a.size()' во втором? :П – hegel5000

2

Я предполагаю, что это какая-то глубоко внутренний компилятор проблема реализации, как на каком этапе автоинъекционаризатор «нажимал» и каково состояние внутреннего представления кода в то время. Когда я пробовал MSVC2017, он работал в большей степени с тем, что можно было бы ожидать. Он автоматически векторизованы update() и update3(), но неupdate2(), с причиной данного 501 для линии 14, которая, как документально:

переменная индукции не является локальным; или верхняя граница не является петлевой инвариантностью.