我已经为卷积矩阵实现了以下程序
#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 卷积矩阵。我已经看到组装输出和自动矢量化只是对 3x3 内核进行了一些更改并合理地提高了性能(快 20 倍注意:不寻常 func 的标量版本比 naive fun 慢)但是 5x5 卷积矩阵没有任何改进
更新:我在问题中添加了简单的实现,并将图片大小更改为 NxM,将卷积矩阵更改为内核,将 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
提前致谢