2012-03-22 12 views
3

Fortranでよく見られるように、私は大規模な並列科学コードを作成しています。私のコードの初めに、私が使用したいソルバーのタイプを教えてくれる設定ファイルを読んだ。今では(メイン実行中)サブルーチンで、私はいくつかの混乱を避けるためにFortranで関数ポインタがある場合

if(solver.eq.1)then 
    call solver1() 
elseif(solver.eq.2)then 
    call solver2() 
else 
    call solver3() 
endif 

編集を持っていることを意味します。私の時間積分ループ内にあると私は内部の3つのネストされたループであるものを持っている。この場合。

私の質問は、solver変数が実行中に変更されないため、初期化手順以外では関数ポインタを使用する方が効率的ではないでしょうか。

明らかに、関数ポインタはF2003です。私がgfortran 4.6を使用している限り、それは問題ではありません。しかし、私は主にBlueGene Pを使用していますが、f2003コンパイラがあるので、Web上で決定的な証拠は見つけられませんでしたが、そこでもうまくいくと思います。

+0

BlueGeneで作業している場合、なぜXLFortranを使用していないのですか?それは非常によく文書化されています。ここから始めることができます。http://www-01.ibm.com/software/awdtools/fortran/ –

+0

申し訳ありませんが明示的ではありません。もちろん、私はBGでXLFortranを使用します。なぜ今日このページを見つけられなかったのですか?間違ったキーワードを探していたに違いありません。プロシージャポインタが正常であることを明確に述べています。どうも。この特定の状況のた​​めに – Azrael3000

+0

私はプリプロセッサを使用し、すべての実行可能ファイルから条件文を取得します。 – agentp

答えて

3

これは私の答えです。分岐に関する主な問題は、CPUが投機的にコードを投機的に実行できないことです。この問題を軽減するために、分岐予測が導入されました(現代のCPUでは非常に洗練されています)。

CPUの予測単位では、関数ポインタによる間接呼び出しが問題になります。コールが実際にどこに行くか予測できない場合、パイプラインが停止します。

私は、CPUが予測の簡単なケースであるため、常に分岐が取られるかどうかを正確に予測すると確信しています。

多分CPUが間接呼び出しを突き抜けて推測するかもしれません。これはあなたが試験が必要な理由です。

できない場合は、ベンチマークで確かに気づくでしょう。

さらに、内側のループからifテストを呼び出すことができますので、頻繁に呼び出されることはありません。これにより、ブランチの実際のパフォーマンスは無関係になります。

+1

あなたの編集を見て、私は私の最後の推奨を強調することができます:内側のループを3回複製し、そのループの外側でif-testを行います。これにより、ブランチがホットパスから移動します。 – usr

+0

それは明らかにオプションです。しかし、それはコードを読むことができなくなります。たとえば、3つのオプションを持つ2つの異なるプロパティを持つ場合、それぞれ9つの異なるifを保持します。 – Azrael3000

+0

おそらくループをソルバに押し込むことができます。その後、関数ポインタを使ってすべてのソルバを実行できますが、パフォーマンスの低下はありません。 – usr

2

初期化時に関数ポインタを1回だけ使用する予定で、BlueGeneでコードを実行している場合は、誤った方向指示の効率が懸念されませんか?一般に、動作する初期化はすべてOKです.1msecの代わりに1秒かかると、おそらく総実行時間に0の影響があります。

明快さのためのコード初期化ルーチン、変更の容易さ、そのようなこと。

EDIT

私の推測ではなく、あなたの現在のコードよりも、関数ポインタを使用すると、実行速度に影響を与えないということです。しかし、それはちょうど(推測された教育の)推測であり、私はあなたがこの質問で集めたデータに非常に興味があります。

+0

私は再びあなたの混乱を参照してください私の質問を読んで申し訳ありません。私は2番目にそれを更新します。 – Azrael3000

+0

さて、私は誰かが分かち合うためのいくつかの洞察を持っているのを待って見ますさもなければ私は少しのベンチマークをするために私の希少な時間を一緒に試してみるでしょう。私はここに投稿します。 – Azrael3000

1

ソルバールーチンが軽微なランタイムをとる場合、IFステートメントの簡単な実行時間は重要ではないようです。 sovlerルーチンにIF文と同等の実行時関数がある場合、実行時間は非常に短いので、どうして気にしますか?これは、最適化が得られないようです。

実行時最適化の最初のルールは、実行時にどの部分がランタイムを消費しているかをコードにプロファイルすることです。それ以外の場合は、重要ではない部分を最適化する可能性があり、何も達成できません。その価値は、他の誰かが最近非常によく似懸念いたものについては

:私は質問に対する答えを見つけることができませんでした簡単に検索した後Fortran Subroutine Pointers for Mismatching Array Dimensions

1

を、私はlittle benchmark自分自身を実行した(Makefileのためthis linkを参照してください&依存関係)。ベンチマークの構成は次のとおりです。

  • 方法B、またはすべてがその1つの整数引数
  • に単純な加算が選択した方法億を呼び出して実行するCを、選択するために、乱数を描きますいずれかの手順ポインタを使用して、時間、またはif文
  • 繰り返し上記5回

と結果CPU E5-2630 v3 @ 2.40GHz上がある:つまり

Time per call (proc. pointer):  1.89 ns 
Time per call (if statement):  1.89 ns 

、パフォーマンスの違いの多くはありません!

+0

あなたは完全なベンチマークを提供していないので、私はサブルーチンを自分で作成しなければなりませんでしたが、 'if statement'バージョンと' -O3'に対して '0 ns'を得ました。それはいくつかの違いです! –

+0

ベンチマークで使用されている他のファイルへのリンクを追加しました! –

+0

モジュールを同じファイルに移動するか、 '-flto'を使うとベンチマークのために' 0s'が得られます。良いベンチマークではありません。 –

関連する問題