時々、FortranはCよりも高速であるか、高速である可能性があることを読みました。それは本当に本当ですか?私はFortranをほとんど知らないことを認めなければなりませんが、これまでに見たFortranコードは、言語にCにはない機能があることを示していませんでした。
それが本当なら、その理由を教えてください。どの言語やライブラリが数の計算に適しているか教えてはいけません。そのためのアプリやライブラリを作成するつもりはありません。興味があります。
言語には同様の機能セットがあります。パフォーマンスの違いは、EQUIVALENCEステートメントが使用されない限り、Fortranがエイリアシングは許可されないと言っているという事実に起因します。エイリアシングのあるコードは有効なFortranではありませんが、これらのエラーを検出するのはプログラマーであり、コンパイラーではありません。したがって、Fortranコンパイラーは、メモリーポインターのエイリアシングの可能性を無視し、より効率的なコードを生成できるようにします。Cのこの小さな例を見てください:
void transform (float *output, float const * input, float const * matrix, int *n)
{
int i;
for (i=0; i<*n; i++)
{
float x = input[i*2+0];
float y = input[i*2+1];
output[i*2+0] = matrix[0] * x + matrix[1] * y;
output[i*2+1] = matrix[2] * x + matrix[3] * y;
}
}
この関数は、最適化後、Fortranの対応する関数よりも実行が遅くなります。なぜそうなのか?出力配列に値を書き込む場合、行列の値を変更できます。結局のところ、ポインタはオーバーラップして同じメモリチャンク(int
ポインタを含む!)を指す可能性があります。Cコンパイラは、すべての計算で4つの行列値をメモリから再ロードするように強制されます。
Fortranでは、コンパイラーはマトリックス値を1回ロードして、それらをレジスターに保管できます。これが可能なのは、Fortranコンパイラーがポインター/配列がメモリー内でオーバーラップしないことを前提としているためです。
幸い、restrict
この問題に対処するために、キーワードと厳密なエイリアスがC99標準に導入されました。最近のほとんどのC ++コンパイラでも十分にサポートされています。このキーワードを使用すると、ポインターが他のポインターとエイリアスしないことをプログラマーが約束するというヒントをコンパイラーに与えることができます。厳密なエイリアスとは、プログラマーが異なるタイプのポインターが重複しないことを約束することを意味します。たとえば、adouble*
はと重複しませんint*
(特定の例外を除いてchar*
、void*
何とでも重複する可能性があります)。
それらを使用すると、CとFortranから同じ速度が得られます。ただし、restrict
パフォーマンスが重要な関数でのみキーワードを使用できるということは、C(およびC ++)プログラムがはるかに安全で簡単に作成できることを意味します。たとえば、無効なFortranコードを考えてみCALL TRANSFORM(A(1, 30), A(2, 31), A(3, 32), 30)
ましょう。ほとんどのFortranコンパイラは警告なしに問題なくコンパイルできますが、一部のコンパイラ、一部のハードウェア、および一部の最適化オプションでのみ発生するバグが発生します。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加