Я реализовал следующую программу для свертки матрицыПочему gcc autovectorization не работает на матрице свертки больше 3x3?
#include <stdio.h>
#include <time.h>
#define NUM_LOOP 1000
#define N 128 //input or output dimention 1
#define M N //input or output dimention 2
#define P 5 //convolution matrix dimention 1 if you want a 3x3 convolution matrix it must be 3
#define Q P //convolution matrix dimention 2
#define Csize P*Q
#define Cdiv 1 //div for filter
#define Coffset 0 //offset
//functions
void unusual(); //unusual implementation of convolution
void naive();
//data
unsigned short int input[N][M] __attribute__((aligned(32))); // input data
unsigned short int output[N][M] __attribute__((aligned(32))); // out put data
unsigned short int kernel[P][Q] __attribute__((aligned(32)));//convolution coefficients
int main(){
struct timespec tStart, tEnd;//used to record the processiing time
double tTotal , tBest=10000;//minimum of toltal time will asign to the best time
int w=0;
do{// this loop repeat the body to record the best time
clock_gettime(CLOCK_MONOTONIC,&tStart);
//function to be executed here :
unusual();
clock_gettime(CLOCK_MONOTONIC,&tEnd);
tTotal = (tEnd.tv_sec - tStart.tv_sec);
tTotal += (tEnd.tv_nsec - tStart.tv_nsec)/1000000000.0;
if(tTotal<tBest)
tBest=tTotal;
} while(w++ < NUM_LOOP);
printf(" The best time: %lf sec in %d repetition for %dX%d matrix\n",tBest,w, MAX1, MAX2);
return 0;
}
//unusual sequential convolution
void unusual(){
int i, j,k,temp;
for (i=P/2; i< N-P/2; i++){
for(j=Q/2; j< M-Q/2; j++){
temp=0;
for(k=0; k< Csize; k++){
temp += (kernel[k/P][k%Q]) * (input[i - (P/2) + (k/Q)][j - (Q/2) + (k%Q)]);
}
output[i][j]=((temp/(Cdiv))+Coffset);
}
}
}
//The naive implementation
inline void naive(){
int i, j,k,l,temp;
for (i=P/2; i< N-P/2; i++){
for(j=Q/2; j< M-Q/2; j++){
temp=0;
for(k = 0; k < P; k++){
for(l = 0; l < Q; l++){
temp += (kernel[k][l]) * (input[i - (P/2)+k][j - (Q/2)+l]);
}
}
output[i][j]=((temp/(Cdiv))+Coffset);
}
}
}
Проблема заключается в том, когда я использую -O3
для автоматической векторизации, он просто работает для матрицы 3x3 свертки. Я видел, что выход Assembly и автоматическая векторная нарисовка просто вносят некоторые изменения в ядро 3x3 и позволяют разумно улучшить производительность (в 20 раз быстрее: скалярная версия необычной функции медленнее, чем наивная забава), но нет улучшения в матрице свертки 5x5
UPDATE: Я добавил наивную реализацию к вопросу и изменил размер изображения на NxM, conv-матрицу на ядро, Cdim1xCdim2 на PxQ и функцию seqConv до необычного для пояснения. Вопрос заключается не в том, чтобы улучшить реализацию необычной функции. Вопрос в том, что все элементы находятся в одних и тех же местах памяти, gcc использует эвристику и т. Д., Почему gcc не может улучшить эту необычную реализацию? ПРИМЕЧАНИЕ: проблема не в наивном исполнении. gcc -O3
улучшают наивную реализацию для ядер 3x3, 5x5 на ~ 7 ускорение. и он также делает для 7x7 и 9x9 на ~ 1,5 ускорения. Чтобы улучшить свертку, я использовал встроенные функции и ускорение более чем в 40 раз по сравнению с наивной реализацией, которая в 2 раза быстрее, чем необычная свертка. Таким образом, моя векторизация ~ 80 раз быстрее, чем моя необычная. Оптимизация ручной настройки не является проблемой. Автоматическая оптимизация векторных изображений является проблемой, и причина неудачи.
команда GCC: gcc -Wall -march=native -O3 -o "%e" "%f"
Платформа: Linux Mint, Skylake, GCC 6.2
Заранее спасибо
Не могли бы вы завершить это достаточно, чтобы оно скомпилировалось? – harold
Конечно, я просто добавил пропущенную часть. программа дыр содержит множество других функций, реализованных с внутренними свойствами AVX2. В программе я выровнял все матрицы с помощью '__attribute __ ((aligned (32))) – Martin
Я скомпилировал с' #define Cdim1 3' в 'clang' и' MVC++', а ускорение над 'gcc -O2' -' 0,97' и '4.34' соответственно ' clang -O3' и 'MVC++ O2' Я включил'/arch: AVX2' и 'Расширение расширения', а также' Ot', но нет различий. – Martin