Я потратил последние несколько дней на чтение autovectorization с помощью gcc 4.7. Я следил за некоторыми примерами, которые я видел в Интернете, и настройка кажется правильной. Но когда я на самом деле запускаю код и сравниваю его с вложением или отключением, во время выполнения нет заметной разницы.Автоинъекция GCC не влияет на время работы, даже когда предположительно «выгодно»
Вот код, я работаю с:
#include <string.h>
#include <stdlib.h>
#include <emmintrin.h>
#include <stdio.h>
#include <math.h>
int main(int argc, char** argv) {
long b = strtol(argv[2], NULL, 0);
unsigned long long int i;
unsigned long long int n = (int)pow(2,29);
float total = 0;
float *__restrict__ x1;
float *__restrict__ y1;
posix_memalign((void *)&x1, 16, sizeof(float)*n);
posix_memalign((void *)&y1, 16, sizeof(float)*n);
float *__restrict__ x = __builtin_assume_aligned(x1,16);
float *__restrict__ y = __builtin_assume_aligned(y1,16);
for (i=0;i<n;i++) {
x[i] = i;
y[i] = i;
}
for (i=0; i<n; i++) {
y[i] += x[i];
}
printf("y[%li]: \t\t\t\t%f\n", b,y[b]);
printf("correct answer: \t\t\t%f\n", (b)*2);
return 0;
}
Некоторые из этих вещей кажется излишним для меня, но было необходимо, чтобы компилятор, чтобы понять, что происходит (особенно тот факт, что данные были выровнены). Переменная «b», которая считывается из командной строки, существует только потому, что я был параноидальным относительно компилятора, полностью оптимизирующего цикл.
Вот команда компилятор, когда vectorizeration включена:
gcc47 -ftree-vectorizer-verbose=3 -msse2 -lm -O2 -finline-functions -funswitch-loops -fpredictive-commoning -fgcse-after-reload -fipa-cp-clone test.c -ftree-vectorize -o v
В основном, это эквивалентно просто используя -O3. Я помещал флаги в себя, чтобы все, что мне нужно было сделать, это удалить «ftree-vectorize» и уметь проверять результат без векторизации.
Вот вывод флага ftree-векторизации-многословная, чтобы показать, что код на самом деле векторизуемый:
Analyzing loop at test.c:29
29: vect_model_load_cost: aligned.
29: vect_model_load_cost: inside_cost = 1, outside_cost = 0 .
29: vect_model_load_cost: aligned.
29: vect_model_load_cost: inside_cost = 1, outside_cost = 0 .
29: vect_model_simple_cost: inside_cost = 1, outside_cost = 0 .
29: vect_model_store_cost: aligned.
29: vect_model_store_cost: inside_cost = 1, outside_cost = 0 .
29: cost model: Adding cost of checks for loop versioning aliasing.
29: Cost model analysis:
Vector inside of loop cost: 4
Vector outside of loop cost: 4
Scalar iteration cost: 4
Scalar outside cost: 1
prologue iterations: 0
epilogue iterations: 0
Calculated minimum iters for profitability: 2
29: Profitability threshold = 3
Vectorizing loop at test.c:29
29: Profitability threshold is 3 loop iterations.
29: created 1 versioning for alias checks.
29: LOOP VECTORIZED.
Analyzing loop at test.c:24
24: vect_model_induction_cost: inside_cost = 2, outside_cost = 2 .
24: vect_model_simple_cost: inside_cost = 2, outside_cost = 0 .
24: not vectorized: relevant stmt not supported: D.5806_18 = (float) D.5823_58;
test.c:7: note: vectorized 1 loops in function.
Обратите внимание, что векторизация выгодно после 3 итераций, и я бегу с 2^29 ~ = 500 000 000 итераций. Поэтому я должен ожидать, что значительно отличается время исполнения, когда векторизация отключена, верно?
Ну, вот время автономной работы кода (я побежал его 20 раз подряд):
59.082s
79.385s
57.557s
57.264s
53.588s
54.300s
53.645s
69.044s
57.238s
59.366s
56.314s
55.224s
57.308s
57.682s
56.083s
369.590s
59.963s
55.683s
54.979s
62.309s
Отбросив что странно ~ 370С останец, что дает среднее время выполнения 58.7s, с стандартное отклонение 6.0s.
Далее я буду компилировать с той же командой, как и раньше, но без -ftree-векторизации флаг:
gcc47 -ftree-vectorizer-verbose=3 -msse2 -lm -O2 -finline-functions -funswitch-loops -fpredictive-commoning -fgcse-after-reload -fipa-cp-clone test.c -o nov
Опять же, запустившего программу 20 раз подряд дает следующие времена:
69.471s
57.134s
56.240s
57.040s
55.787s
56.530s
60.010s
60.187s
324.227s
56.377s
55.337s
54.110s
56.164s
59.919s
493.468s
63.876s
57.389s
55.553s
54.908s
56.828s
Снова выбросив выбросы, это дает среднее время работы 57,9 с стандартным отклонением 3,6 с.
Таким образом, эти две версии имеют статистически неразличимые времена автономной работы.
Может ли кто-нибудь указать мне на то, что я делаю неправильно? Не порождает ли «порог прибыльности» компилятор, что я думаю, что это значит? Я очень ценю любую помощь, которую люди могут мне дать, я пытался понять это на прошлой неделе.
EDIT:
Я осуществил изменения, которые @nilspipenbrinck предложенных, и это, кажется, работает. Я вставил векторный цикл в функцию и назвал эту функцию лодкой раз. Относительное время выполнения составляет 24,0 с (сигма < 0,1 с) без векторизации против 20,8 с (сигма < 0,2 с) для векторизации или 13% -ное улучшение скорости. Не так много, как я надеялся, но по крайней мере теперь я знаю его работу!Спасибо, что нашли время, чтобы посмотреть на мой вопрос и написать ответ, я очень ценю это.
Есть ли какая-либо особая причина для тестирования устаревшей версии компилятора? Какое у вас оборудование? – Drop
Локализация ссылок - это большая проблема для современных процессоров. Ваша программа не имеет, ее время выполнения полностью зависит от стоимости доступа к ОЗУ. –
@Drop Я планирую получить эту работу на кучу разных компьютеров в моей лаборатории, и все они используют этот компилятор. Фактически, версия, которую они используют, старше этого, gcc4.4 или ниже. Но некоторые из функций, которые я хотел поэкспериментировать, не возникали до 4.7. У меня нет возможности обновлять компиляторы, или я бы это сделал. – user2635263