2016-09-05 17 views
0

バージョン1:OpenMPの、インライン関数、および静的変数(無地C)

inline double func(int i){ 
    double X; 
    X=sqrt(2)*i; 
    return X; 
} 

バージョン2:

inline double func(int i){ 
    static double X; 
    X=sqrt(2)*i; 
    return X; 
} 

バージョン3:

inline double func(int i){ 
    static double X; 
    #pragma omp threadprivate(X) 
    X=sqrt(2)*i; 
    return X; 
} 

func()関数は、ですopenmpブロックの内部で呼び出されます:

#pragma omp for default(shared) private(i) schedule(static) 
for(i=istart;i<istop;i++){ 
    val[i]=func(i); 
} 

func()の中で、最も安全で安全なバージョンは何ですか?すべての3つのバージョンは完璧ですか?

+0

最初に「X」とは何ですか?バージョン2はスレッドセーフではありませんが、 'X'が必要なのかどうかわからなくてもあまり知られていません。 – Gilles

+0

はいバージョン2はスレッドセーフではありません。なぜあなたはそれを静的と宣言していますか?最初のバージョンでは、Xは各スレッドに対してプライベートなので、安全です。最初は見た目は安全だと思われますが、バージョン3はテストする必要があります。 – itsnevertoobadtoaskforhelp

+0

@ Gillesこれは単なる例であり、Xはiに依存する一般的な計算の結果です @itsnevertoobadtoaskforhelp 'func'がループ内にあり、それは時間の零点と呼ばれるので静的と宣言したいと思います。 Xは静的なので、 'func'の各呼び出しで初期化する必要はありません。 – cipper

答えて

0

静的変数を関数内に宣言すると(インラインでもなくても問題ありません)、コンパイラは一意の名前(通常は関数名と変数名の組み合わせ)を持つグローバル変数を生成します。静的関数変数とグローバル変数の違いは、可視性の範囲内のみです。 バージョン2はスレッドセーフではありません。

バージョン1と3を比較しましょう。バージョン1はXがレジスタであるために少し速く、メインメモリに格納する必要はありません。速度差がinlineまたはopenmpに依存しないので、私は単純な例を紹介します:

#include <math.h> 

double func1(int i){ 
    double X; 
    X=M_SQRT2*i; 
    return X; 
} 

double func2(int i){ 
    static double X; 
    X=M_SQRT2*i; 
    return X; 
} 

はそれをコンパイルします。gcc -S -O3 test.cここ

-Sアセンブラファイルtest.s-O3を生成することで、最適化を可能にするためです。

func1: 
.LFB3: 
    .cfi_startproc 
    cvtsi2sd %edi, %xmm0 
    mulsd .LC0(%rip), %xmm0 
    ret 
    .cfi_endproc 

func2: 
.LFB4: 
    .cfi_startproc 
    cvtsi2sd %edi, %xmm0 
    mulsd .LC0(%rip), %xmm0 
    movsd %xmm0, X.2782(%rip) 
    ret 
    .cfi_endproc 

func2が1行長く表示されることがあります。 命令movsd %xmm0, X.2782(%rip)は結果をメインメモリに格納します。 X.2782は生成されたグローバル変数です。

バージョン1が優れています。

+0

ありがとうございました。しかし、並列ブロックで実行しているとき、私のv3はより速いですか? – cipper

+0

@cipper、No.バージョン1は高速です。最適化後(コンパイラで最適化を有効にすることを忘れないでください)、バージョン1には変数Xがありません。 バージョン3には、メインメモリにXを格納する追加の命令があります。 – petrmikheev

+0

'sqrt(2)'の代わりに 'M_SQRT2'を使います。ループを数回速くします。コンパイラ(少なくとも 'gcc'と' g ++ ')は、' sqrt(2) 'がconstであることを自動的に理解することはできません。 – petrmikheev

関連する問題