4

私はいくつかのFortranコードをIntelFortranコンパイラーifortでコンパイルしています。gprofを使用してプロファイルテストを実行すると、ほとんどの場合IO操作で使用されていることがわかります。ファイルの終わりを見つけると思いますが、これに関するドキュメントはこれ以上見つかりません。

index % time    self  children    called     name
                                                 <spontaneous>
[1]     20.6    0.07    0.00                 _IO_wfile_seekoff [1]
-----------------------------------------------
                                                 <spontaneous>
[2]     20.6    0.07    0.00                 sforcepf_ [2]
-----------------------------------------------
                                                 <spontaneous>
[3]     20.6    0.02    0.05                 _IO_wfile_underflow [3]
                0.01    0.04  258716/258717      strncmp [4]
-----------------------------------------------
                0.00    0.00       1/258717      _IO_wdefault_doallocate [15]
                0.01    0.04  258716/258717      _IO_wfile_underflow [3]
[4]     14.7    0.01    0.04  258717         strncmp [4]
                0.04    0.00 3104592/3109256     strerror_r [5]
-----------------------------------------------
                0.00    0.00    4664/3109256     __strcmp_sse42 [14]
                0.04    0.00 3104592/3109256     strncmp [4]
[5]     11.8    0.04    0.00 3109256         strerror_r [5]
-----------------------------------------------

したがって、問題は、このIOがLinuxに固有なのか、ifortに固有なのか、それともFortranに固有なのかということです。私はこのコードを最適化しようとしていますが、グーグルでこの用語に関する有用な情報を見つけられませんでした。

4

3 に答える 3

9

Fortran ステートメントを記述します。インテル Fortran コンパイラーは、これらのステートメントをシステム関数の呼び出しを含むアセンブラーに変換します。たとえば、strncmp文字列の一部を比較する ISO C 標準関数です。したがって、文字列を比較する Fortran ステートメントを記述しているように見えますが、インテル Fortran コンパイラーは比較を実装するために既存の関数を呼び出しています。これらのシステム関数の一部は、プラットフォームで提供されるさらに基本的な関数への呼び出しによって (部分的に) 実装されます。

gprofコンパイルの製品で参照されていることがわかった関数への呼び出しを示しています。表示される内容のほとんどは Linux I/O に固有のものです。Windows マシンでは、I/O は異なる名前の同様の関数を使用します。表示される内容の一部は Intel コンパイラに固有のものであり、すべての Intel コンパイラが同じ (Intel が作成した) 関数を何らかの操作に使用し、その関数がプラットフォーム固有の低レベル関数を使用している可能性があります。

これらの低レベル関数を書き直す準備ができておらず、同じ関数を使用する他のプログラムでそれらを台無しにするリスクを冒さない限り、実行できる最適化は、呼び出しの頻度を減らすことだけです。たとえば、ファイルの末尾を超えて読み取るのは高価な I/O 操作であると考える理由があり、プログラムの戦略が末尾を超えて読み取るまでファイルを読み取り、発生したエラーに対処する場合、次に、優れたプログラム戦略を実装することをお勧めします。これは、戦略の結果を処理する低レベルの I/O ルーチンを書き直すよりも簡単です。

于 2012-04-10T13:08:51.667 に答える
3

あなたはFortranI/O操作を見ているようです。フォーマットされたI/Oはで非常に遅いですifort。標準入力/標準出力リダイレクトを使用すると、さらに悪化します。パイプの場合はさらに悪化します-Intelのドキュメントは特にそれを行わないように警告しています。gfortranそれほど悪くはありませんが、それでもかなり遅いです。

いくつかの可能性は次のとおりです。

  • I / O呼び出しをできるだけ少なくするようにしてください(たとえば、ループから外す)
  • リダイレクトを避け、代わりにファイルを直接読み取り/書き込みします
  • チェックblocksizebuffercountおよびその他のI/O関連オプションopen()

これが不十分で、I / Oが主要なボトルネックである場合は、次のことを検討してください。

  • でストリームI/Oを調べるとifort、より高速で、複数の呼び出しを行わないように、自分でバッファリングするなどのことができます。ただし、他のコンパイラがまだサポートしていないか、別の方法でサポートしている可能性があるため、移植性の問題が発生する可能性があります。標準の入出力では実行しないでください(ifortで動作する可能性がありますが、文書化されておらず、他のコンパイラでは動作しません)。
  • C関数を呼び出すために使用iso_c_bindingします。たとえば、標準出力に書き込む場合はputs()、libcから呼び出すことができます。これは標準であるため、さらに高速で、実際には非常に移植性があります。実際、私が実行したすべてのOS(Win32 / linux64 / sparc solaris)のすべてのコンパイラは、とにかくlibcを必要とします(そして自動的にリンクします)。しかし、それはかなり醜いので、nullで終了するなどのことを自分で処理する必要があります(たとえば、ラッパー関数を作成することによって)。これにより、コードが不明瞭になり、バグが発生する可能性があります。
  • これらの方法を同じファイルの通常のI/Oと混在させないでください!!

コードで文字列の比較を明示的に行っている場合、これらも最終的には呼び出されstrncmp()ます。文字列操作もifortで少し遅いので(I / Oほど悪くはありませんが)、たくさんの比較をしている場合は、直接呼び出すことで数秒かかるかもしれませんがstrncmp()、それに対してアドバイスします-ゲインはそれほど大きくはなく、コードが不明瞭になります。

于 2012-04-11T09:33:12.117 に答える
3

任意の言語で次のように書くとします。

loop for a long time
  write something to somewhere

gprofでプロファイリングします。

gprofは、IO またはその他のブロック状態の間、サンプリングを一時停止します。このプログラムは、ごくわずかな期間しか実行しませんが、費やすサイクルのほとんどは、IO を開始して終了を待つ組み込みライブラリ ルーチンに出入りするために費やされます。

したがって、プログラムがそのようなものである場合、それが表示されることは驚くべきことではありません。

この問題にはさらに多くのことがあります。

于 2012-04-10T19:52:46.617 に答える