2017-12-27 41 views
3

は、次のコードを確認してください:なぜ "#pragma omp simd"はgccコンパイラで "-O2"のパフォーマンスが大幅に向上するのですか?

#include <stdio.h> 
#include <omp.h> 

#define ARRAY_SIZE (1024) 
float A[ARRAY_SIZE]; 
float B[ARRAY_SIZE]; 
float C[ARRAY_SIZE]; 

int main(void) 
{ 
    for (int i = 0; i < ARRAY_SIZE; i++) 
    { 
     A[i] = i * 2.3; 
     B[i] = i + 4.6; 
    } 

    double start = omp_get_wtime(); 
    for (int loop = 0; loop < 1000000; loop++) 
    { 
     #pragma omp simd 
     for (int i = 0; i < ARRAY_SIZE; i++) 
     { 
      C[i] = A[i] * B[i]; 
     } 
    } 
    double end = omp_get_wtime(); 
    printf("Work consumed %f seconds\n", end - start); 
    return 0; 
} 

ビルドをし、私のマシン上でそれを実行し、それが出力:

$ gcc -fopenmp parallel.c 
$ ./a.out 
Work consumed 2.084107 seconds 

私は、 "#pragma omp simd" をコメントアウト構築し、再びそれを実行した場合:

$ gcc -fopenmp parallel.c 
$ ./a.out 
Work consumed 2.112724 seconds 

"#pragma omp simd"は大きなパフォーマンスを得ることはできません。 "#pragma omp simd "と

$ gcc -O2 -fopenmp parallel.c 
$ ./a.out 
Work consumed 0.446662 seconds 

::私は-O2オプション、ノー" #pragma omp simd" を追加した場合でも、

$ gcc -O2 -fopenmp parallel.c 
$ ./a.out 
Work consumed 0.126799 seconds 

は、私たちは大きな改善を見ることができます。 -O3を使用した場合でも、一切 "#pragma omp simd ":

$ gcc -O3 -fopenmp parallel.c 
$ ./a.out 
Work consumed 0.127563 seconds 

" #pragma omp simd" とは:

$ gcc -O3 -fopenmp parallel.c 
$ ./a.out 
Work consumed 0.126727 seconds 

私たちは、結果が再び似て見ることはできません。

なぜ#pragma omp simdgccコンパイラの下で-O2のパフォーマンスが大幅に向上しますか?

+1

O3を使用するときにコンパイラのコードをさらに最適化し、simd命令を利用する可能性が高いように見えます。結果のアセンブリを比較しましたか? – Harald

答えて

7

-O0it's a total waste of timeでタイミングを忘れてしまいます。自動ベクトル化

gcc -O3試みすべてのループは、そのOpenMPプラグマを使用するだけでそれ以外-ffast-mathrestrict修飾子、または他の障害物との唯一の自動ベクトル化コンパイラが満足しているすべての可能な状況下で正確さとなるループのためにあなたを助けます純粋なCの自動ベクトル化のために(明らかにここでの障害はありません:ここでは縮小ではなく、あなたは完全に垂直の操作しか行いません。 gcc -O2-ftree-vectorizeを有効にしていないため、OpenMPプラグマを使用して特定のループでそれを要求すると、自動ベクトル化されます。


clang-O2で自動ベクトル化を可能にすることに注意してください。


GCCの自動ベクトル化手法は、OpenMPとバニラで異なる場合があります。 IIRCでは、OpenMPループの場合、gccはアラインメント境界に達するまでスカラに行くのではなく、アラインされていないロード/ストアを使用することがあります。たとえその事実がコンパイル時に知られていなくても、データが実行時に整列されていれば、これはAVXの欠点ではありません。 gccの完全に展開されていない起動/クリーンアップコードに対して、膨大なコードを膨大に保存します。

OpenMPを使用してSIMDベクトル化を要求している場合は、キャッシュライン分割を避けるためにデータを整列している可能性があります。しかし、Cは、floatへのポインタがfloatの幅より多く整列しているという事実を渡すのが非常に便利ではありません。 (特にそうでない場合はまれにしか機能しない場合でも、は通常になります)。

+2

gccでは、プラグマsimdは他のコンパイラよりも小さな役割を与えます。そうでなければ必要な制限修飾子を省略した場合でも、(-O2/3の)違いがあります。 – tim18

+0

@ tim18:いい点です。それは整数コードにも当てはまる「何か」の一部です。 –

+2

私はGCCとClangのデフォルトをICCのように少なくとも '-O2'にしたいと思っています。私は '-O0または-O1'の点を見ていません。私がデバッガを使用した回数は、とにかく最適化されたコードにしか現れませんでした。私はこれをしばらく聞きたいのですが、 '-O1'のポイントは何ですか? –

関連する問題