2017-04-05 186 views
0

我對SIMD相當新穎,想試試看能否讓GCC爲我引導一個簡單的動作。矩陣乘法的自動矢量化

所以我看着this post,想要做更多或更少的相同的事情。 (但在Linux 64位GCC 5.4.0,對於KabyLake處理器)

我基本上是有這個功能:

/* m1 = N x M matrix, m2 = M x P matrix, m3 = N x P matrix & output */ 
void mmul(double **m1, double **m2, double **m3, int N, int M, int P) 
{ 
    for (i = 0; i < N; i++) 
     for (j = 0; j < P; j++) 
     { 
      double tmp = 0.0; 

      for (k = 0; k < M; k++) 
       tmp += m1[i][k] * m2[k][j]; 

      tmp = m3[i][j]; 
     } 
    return m3; 
} 

其中我編譯-O2 -ftree-vectorize -msse2 -ftree-vectorizer-verbose=5,但我沒有看到任何消息矢量已完成。

如果有人能幫助我,那將非常感激。

+2

'-fopt-info-all-vec'(詳見doc文檔)給出了更多信息。 '-fopt-info-missed-vec'輸出中的一個關鍵要素是「減少:不安全的fp數學優化:tmp_40 = _16 + tmp_49;」這實質上意味着你需要-ffast-math(或稍微弱一點)來進行矢量化。 –

回答

2

在你的命令中沒有向量化信息!您可以使用-fopt-info-vec來打開矢量化報告。但是,不要依賴它。編譯器有時會存在(他們矢量化和報告它,但不使用它!),你可以改進這些改進!爲此,你可以測量加速。首先,禁用矢量化並測量時間t1。然後啓用並測量時間t2。如果它大於1,那麼加速將會是t1/t2,它說編譯器改進了,如果1沒有改進,如果小於一個,它說編譯器自動矢量化器毀了你!另一種方法是您可以將-S添加到您的命令中,並在分開的.s文件中查看彙編代碼。

注:,如果你想看到的自動向量化功率增加-march=native和刪除-msse2

UPDATE:當你使用一個變量,一個NM等作爲循環計數器,你可能看不到量化。因此,您應該使用constants代替。根據我的經驗,矩陣 - 矩陣乘法可以使用gcc 4.8, 5.4 and 6.2進行矢量化。其他編譯器如clang-LLVMICCMSVC也將其向量化。正如在評論中提到的,如果您使用doublefloat數據類型,則可能需要使用-ffast-math這是-Ofast優化級別中的啓用標誌,說您不需要高精確度的結果(大多數情況都是如此)。這是因爲複製者更擅長於浮點操作。

+0

謝謝一堆:) –

+0

@WorkofArtiz和Martin:'gcc -O3'啓用'-ftree-vectorize'和其他一些東西。請注意,「-Ofast」是「-O3 -ffast-math」,而不是「-O2」。無論如何,我建議比較'-O3 -ffast-math -march = native'與'O3 -ffast-math -march = native -fno-tree-vectorize'。 –

+1

關於常量與可變循環計數的好處。只要循環迭代計數在第一次迭代之前已知,gcc和clang通常可以進行矢量化。 (但他們永遠不能像'while(a [i ++]!= 2){}')那樣矢量化搜索循環。儘管如此,他們通常在編譯時常量循環計數方面做得更好。 –