[解決済み] FortranはC言語よりも重い計算を最適化しやすいですか?
質問
時々、重い計算にはCよりFortranの方が速い、または速いという記事を読みます。本当にそうなのでしょうか?私はFortranをほとんど知らないのですが、今まで見たFortranのコードでは、Cにない特徴があるようには見えませんでした。
もし本当なら、その理由を教えてください。数字計算をするのに適した言語やLibを教えてください。そのためのアプリやLibを書くつもりはありません。
どのように解決するのですか?
両言語は似たような機能セットを持っています。パフォーマンスの違いは、FortranではEQUIVALENCE文が使われていない限り、エイリアシングは許されないとされていることに起因します。エイリアシングがあるコードは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の対応する関数よりも実行速度が遅くなります。なぜでしょうか?出力配列に値を書き込むと、matrixの値を変更する可能性があるからです。結局、ポインタが重なって、メモリの同じチャンクを指す可能性があるのです(その中には
int
のポインターを使用します!) Cコンパイラは、すべての計算のために、4つの行列の値をメモリから再ロードすることを余儀なくされます。
Fortranでは、コンパイラは行列の値を一度ロードして、レジスタに格納することができます。これは、Fortranコンパイラが、ポインタや配列がメモリ上で重ならないことを前提にしているからです。
幸いなことに
restrict
キーワードとストリクトエイリアスがC99標準に導入され、この問題に対処しています。最近では、ほとんどのC++コンパイラでも十分にサポートされている。キーワードは、プログラマがポインタが他のポインタとエイリアスしないことを約束するヒントをコンパイラに与えることを可能にします。strict-aliasing は,異なる型のポインタが決して重ならないことをプログラマが約束することを意味し,たとえば
double*
とは重なりません。
int*
(ただし
char*
と
void*
は何にでも重なります)。
それらを使えば、CとFortranから同じスピードが得られるでしょう。しかし、その能力は
restrict
キーワードは、パフォーマンス上重要な関数にのみ使用することで、C(およびC++)のプログラムはより安全で書きやすくなります。例えば、無効なFortranのコードを考えてみましょう。
CALL TRANSFORM(A(1, 30), A(2, 31), A(3, 32), 30)
これは、ほとんどのFortranコンパイラが何の警告も出さずに喜んでコンパイルしますが、一部のコンパイラ、一部のハードウェア、一部の最適化オプションでのみ表示されるバグを引き起こします。
関連
-
libc++abi.dylib: NSException タイプの捕捉されない例外で終了するエラー
-
C: 1を求める! + 2! + 3! + ... + n! (ループ)
-
[解決済み] Windows用Cコンパイラ?[クローズド]
-
[解決済み] c または c++ 用のシンプルな 2 次元クロスプラットフォームグラフィックスライブラリ?[クローズド]
-
[解決済み] C - Setデータ構造を実装するには?
-
[解決済み] Cコードの単体テスト【終了しました
-
[解決済み] Collatz予想の検証を行うC++のコードは、なぜ手書きのアセンブリよりも高速に動作するのでしょうか?
-
[解決済み] Project Eulerとの速度比較。CとPythonとErlangとHaskellの比較
-
[解決済み] なぜGCCは、速度の代わりにサイズに最適化すると、15-20%速いコードを生成するのですか?
-
[解決済み】Javaで(a != 0 && b != 0)よりも(a*b != 0)の方が速いのはなぜか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
VSCodeでCプログラムを書くとエラーになる:ソースファイル "stdio.h" を開くことができない
-
Solve Dev-c++ [エラー] 'for' ループの初期宣言は、C99 または C11 モードでのみ許可されます。
-
[解決済み] stdinとSTDIN_FILENOの違いは何ですか?
-
[解決済み] C - Setデータ構造を実装するには?
-
[解決済み] C言語では「?」演算子は何をするのですか?
-
[解決済み] printfにおけるdoubleの正しい書式指定子
-
[解決済み] フリーは、どのように無料化を知っているのですか?
-
[解決済み] なぜalloca()の使用はグッドプラクティスとみなされないのでしょうか?
-
[解決済み] ストラクチャーとユニオンの違い
-
[解決済み] C言語でファイルサイズを取得するには?[重複]する