重い計算のためにFortranはCよりも最適化が簡単ですか?


410

Fortranは重い計算ではCよりも高速である、または高速になる可能性があることを時々読んだ。それは本当ですか?私はFortranをほとんど知らないことを認めなければなりませんが、これまでに見たFortranコードは、Cにはない機能が言語にあることを示していませんでした。

それが本当なら、その理由を教えてください。数の計算に適した言語やライブラリを教えないでください。それを行うためにアプリやライブラリを作成するつもりはありません。ただ興味があるだけです。


53
以下に与えられた回答からの主観的な主観 正しいタイトルは、「FortranコンパイラーがCコンパイラーよりも最適化されたコードを生成する可能性がある根本的なアーキテクチャ上の理由はありますか」ですが、それはほんの一部です。
マーティンベケット

3
タイトルの質問は誤解であるほど主観的なものではないと思います。より詳細な質問は主観的ではありません。
jfm3 2008

1
答えは「はい」と「いいえ」で、コンパイラ、ソース、CPU、メモリレイアウトなどによって異なります。
user7116 2008

1
質問や回答が主観的だとは思いません。しかし、このフラグが誰にとっても役立つと思うなら、私はそれで大丈夫です。
quinmars 2008

2
@sixlettervariablesあなたと私はすでに答えを知っていますが、キャリアの早い段階でほとんどの人に起こる質問であり、答えを理解することが重要です。否定的なコメントを投稿するのではなく、同意する回答を見つけて+1を付けてみませんか
MarkJ

回答:


447

言語には同様の機能セットがあります。パフォーマンスの違いは、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では、コンパイラーはマトリックス値を一度ロードして、レジスターに保管できます。Fortranコンパイラーは、ポインター/配列がメモリー内でオーバーラップしないと想定しているため、これを行うことができます。

幸い、restrictこの問題に対処するために、キーワードと厳密なエイリアスがC99標準に導入されました。最近のほとんどのC ++コンパイラでも十分にサポートされています。このキーワードを使用すると、ポインターが他のポインターとエイリアスしないことをプログラマーが約束するヒントをコンパイラーに与えることができます。厳格なエイリアシング手段プログラマの約束異なるタイプのポインタは、オーバーラップ、例えば決してそのことdouble*ではない重複するとint*(という特定の例外とchar*し、void*何と重複することができます)。

それらを使用すると、CとFortranで同じ速度が得られます。ただし、restrictパフォーマンスが重要な関数でのみキーワードを使用できるということは、C(およびC ++)プログラムの方がはるかに安全で簡単に記述できることを意味します。たとえば、無効なFortranコードを考えてみCALL TRANSFORM(A(1, 30), A(2, 31), A(3, 32), 30)ましょう。ほとんどのFortranコンパイラは警告なしで問題なくコンパイルされますが、一部のコンパイラ、一部のハードウェア、および一部の最適化オプションでのみ表示されるバグを引き起こします。


26
すべて真実かつ有効です、ジェフ。ただし、「エイリアスを想定しない」スイッチは安全だとは考えていません。他のプロジェクトから継承されたコードを非常に微妙な方法で破壊する可能性があるため、使用しない方がよいでしょう。その理由で私は制限ナチになった:-)
Nils Pipenbrinck '28

3
2つ目のポイントとして、エイリアスコンパイラなしのスイッチを使用する必要はありません。ポインタベースのロードが最初に自動変数に割り当てられるようにコードを記述してから、そこから自動変数を操作します。より冗長に見えますが、コンパイラーによって完全に最適化されます。
トールジェフ

33
良い例は、memcpy()とmemmove()の単なる存在です。memcpy()とは異なり、memmove()は重複領域を処理するため、memcpy()はmemmove()よりも高速です。この問題は、誰かが1つではなく2つの関数を標準ライブラリに含めるのに十分な理由でした。
jfs 2008

12
私はそれがセバスチャンのポイントだったと思います-Cメモリ処理の複雑さ/柔軟性のために、メモリの移動と同じくらい単純なものでもトリッキーです。
マーティンベケット

3
あなたのcall transform例はあまり意味がありません。
ウラジミールF

163

はい、1980年に。2008年に?依存する

私が専門的にプログラミングを始めたとき、Fortranの速度の優位性はまさに挑戦されていました。ドブス博士でそれについて読んだり、この記事について年配のプログラマーに言ったりしたことを覚えている-彼らは笑った。

したがって、私はこれについて理論的および実用的な2つの見解を持っています。理論上、今日のFortranには、C / C ++や、アセンブリコードを許可する言語に固有の利点はありません。実際には、 Fortranは今日でも、数値コードの最適化を中心に構築された歴史と文化の遺産の利点を享受しています。

Fortran 77までは、言語設計の考慮事項は最適化が主な焦点でした。コンパイラーの理論とテクノロジーの状態により、これは多くの場合、コンパイラーにコードの最適化のベストショットを与えるために、機能と機能を制限することを意味しました。良い例えは、Fortran 77を、スピードのために機能を犠牲にしたプロのレースカーと考えることです。最近では、コンパイラーはすべての言語で改善されており、プログラマーの生産性向上のための機能はより高く評価されています。ただし、科学計算の速度に主に関心がある場所はまだあります。これらの人々はおそらく、自分自身がFortranプログラマーであった人々からコード、トレーニング、文化を継承しています。

コードの最適化について話し始めると、多くの問題があり、これを感じ取る最良の方法は、高速な数値コードを使用することを仕事とする人々の居場所を潜むことです。ただし、このような非常に機密性の高いコードは、通常、コード行全体のごく一部であり、非常に特殊化されていることに注意してください。そのようなコードの主な懸念

Fortranの歴史と文化について学ぶのに最適な場所は、ウィキペディアです。Fortran Wikipediaのエントリーはすばらしいものであり、Fortranコミュニティーにとって価値のあるものにするために時間と労力を費やしてくれた方々に大変感謝しています。

(この回答の短縮版は、Nilsによって開始された優れたスレッドでのコメントでしたが、私にはそれを行うためのカルマがありません。実際、私はおそらく何も書かなかったでしょうが、このスレッドには実際の炎の戦争と言語の偏見とは対照的に、情報コンテンツと共有。これは、この主題に関する私の主な経験です。私は圧倒され、愛を共有する必要がありました。)


1
リンク:web.archive.org/web/20090401205830/http : //ubiety.uwaterloo.ca/…機能しなくなりました。代替リンクはありますか?
nathanielng 2015

64

Fortranは、コンパイラの最適化を念頭に置いてある程度設計されています。この言語は、コンパイラーが並列処理を利用できる配列操作全体をサポートします(特にマルチコアプロセッサーで)。例えば、

密行列の乗算は単純です:

matmul(a,b)

ベクトルxのL2ノルムは次のとおりです。

sqrt(sum(x**2))

さらにFORALLPURE&などのステートメントELEMENTAL手続きなどのコードの最適化に役立ちます。この単純な理由により、Fortranのポインターでさえ、Cのように柔軟ではありません。

今後のFortran規格(2008)には、並列コードを簡単に記述できるCo-Arrayがあります。G95(オープンソース)とCRAYのコンパイラはすでにそれをサポートしています。

そのため、コンパイラはC / C ++よりも最適化/並列化できるため、Fortranは高速でありえます。しかし、やはり他のすべてのものと同様に、良いコンパイラと悪いコンパイラがあります。



1
forallコンパイラーがコードを適切に最適化できなかったため、この構造は推奨されません。交換はdo concurrentです。また、sqrt(sum(x**2))コンパイラーはおそらくvector全体を構築するため、コードは非効率に見えx**2ます。ループの方が良いと思いますが、組み込みnorm2関数を呼び出すのが間違いなく最善です。
A. Hennink 2017

39

言語を知らないことからの答えがたくさんあるのはおかしいです。これは特に、FORTRAN 77のコードを開いて古く、弱点について話し合ったC / C ++プログラマーに当てはまります。

速度の問題は主にC / C ++とFortranの間の問題だと思います。巨大なコードでは、それは常にプログラマーに依存します。Fortranが優れている言語の機能と、Cが行う機能のいくつかがあります。したがって、2011年には、どちらがより速いかを実際に言うことはできません。

言語自体については、Fortranは現在、完全なOOP機能をサポートしており、完全に下位互換性があります。私はFortran 2003を徹底的に使用してきましたが、それを使用できて本当に良かったと思います。いくつかの側面では、Fortran 2003はまだC ++の背後にありますが、使用法を見てみましょう。Fortranは主に数値計算に使用されますが、速度上の理由から、誰も豪華なC ++ OOP機能を使用していません。ハイパフォーマンスコンピューティングでは、C ++を使用する場所がほとんどありません(MPI標準を確認すると、C ++が非推奨になっていることがわかります)。

今日では、FortranとC / C ++を使用して混合言語プログラミングを簡単に行うことができます。FortranにはGTK +のインターフェースさえあります。無料のコンパイラ(gfortran、g95)と多くの優れた商用コンパイラがあります。


8
将来のプロジェクトのためにC ++から移行するか、C ++プロジェクトを別の言語に書き直すソース、特定の経験、または科学研究所/高性能コンピューティング機関を追加していただけませんか。高性能モデリングにc ++を多用している少なくとも2つの科学機関、SandiaとCERNを知っているからです。さらに、Sandiaは、モデリングソフトウェア(LAMMPS)の1つをfortranからc ++に変換し、多くの素晴らしい機能強化を追加しました。
Zachary Kraus

7
LAMMPSは、言語の最新の機能のほとんどを利用しない、非常にシンプルなC ++で記述されています。これは、Cを知っているFortranプログラマがC ++ 98を学んだ後に書くC ++を表しています。これはLAMMPSの記述が不十分であると言っているのではなく、HPCでC ++を主張する際に引用したい例ではないということです。
ジェフ

30

Fortranが高速になる理由はいくつかあります。しかし、それらが重要な量は非常に重要ではないか、とにかく回避することができるので、重要ではありません。今日Fortranを使用する主な理由は、レガシーアプリケーションを維持または拡張することです。

  • 関数のPUREおよびELEMENTALキーワード。これらは副作用のない関数です。これにより、コンパイラが同じ関数が同じ値で呼び出されることがわかっている特定のケースで最適化が可能になります。注:GCCは、言語の拡張機能として「純粋」を実装しています。他のコンパイラも同様です。モジュール間分析でもこの最適化を実行できますが、困難です。

  • 個々の要素ではなく配列を処理する関数の標準セット。sin()、log()、sqrt()のようなものは、スカラーの代わりに配列を取ります。これにより、ルーチンの最適化が容易になります。自動ベクトル化は、これらの関数がインラインまたは組み込みの場合、ほとんどの場合に同じ利点を提供します

  • 組み込みの複合型。理論的には、これによりコンパイラーが特定の場合に特定の命令を並べ替えたり削除したりできるようになりますが、struct {double re、im; }; Cで使用されているイディオム。演算子はfortranの複雑な型を処理するため、開発が速くなります。


1
「しかし、おそらく{ double re, im; };Cで使用されているstruct イディオムを使用しても同じ利点が得られるでしょう。」Cコンパイラーは、その構造体を呼び出し側スタックがスペースを割り当ててsret形式で返し、それを埋める呼び出し先にポインターを渡します。これは、Fortranコンパイラーが行うようにレジスターに複数の値を返すよりも数倍遅いです。C99が複雑な特殊なケースでこれを修正したことに注意してください。
Jon Harrop

あなたの主な理由に同意するかどうかはわかりません。私は個人的には、配列と数学関数がコードの最も重要な部分である数学の重いコードにfortranを使用するのが好きです。しかし、多くの政府機関や銀行で、レガシーコードを維持または拡張するために引き続きFortranを使用している事実を知っています。私は個人的にfortranを使用して、私の博士号の教授のコードを拡張しました。委員会が書いた。
ザカリークラウス

「今日Fortranを使用する主な理由は、レガシーアプリケーションの維持または拡張である」というあなたの発言は、完全に間違っています。Fortranが提供する機能(特に数学的アプリケーション)にかなり近い他のプログラミング言語もまだ見ていません。すばらしい配列のサポート、組み込みの複雑な算術演算、純粋関数または要素関数など、すでにいくつかの名前を付けていますが、もっと多くの名前を付けることもできます。それだけでも、上のステートメントが間違っていることを証明するには十分です。
パプ

28

Fortranを支持する重要な点は、それがベクトルおよび配列ベースの数学を表現するのに少し適した言語であるということです。上記で指摘したポインター分析の問題は実際に現実的です。移植可能なコードでは、コンパイラーに何かを伝えることができるとは想定できないからです。ドメインがどのように見えるかに近い方法で計算を表現することには、常に利点があります。Cは実際には配列をまったく持っていません。よく見ると、そのような動作をするものだけです。Fortranには本当の難易度があります。これにより、特定のタイプのアルゴリズム、特に並列マシン用のコンパイルが容易になります。

ランタイムシステムや呼び出し規約などの詳細については、Cと最新のFortranは非常に似ているため、何が違いを生むのかわかりません。ここでのCは実際にはベースCであることに注意してください。C++はまったく異なる問題であり、パフォーマンス特性が大きく異なります。


25

ある言語が別の言語よりも速いということはありません。そのため、適切な答えはnoです。

「CコンパイラYでコンパイルされた同等のコードよりもFortranコンパイラXでコンパイルされたコードは高速ですか?」もちろん、その質問への答えは、選択した2つのコンパイラによって異なります。

「コンパイラで最適化に費やされたのと同じ量の作業を行うと、どのコンパイラがより高速なコードを生成するのか」という質問に沿って質問することもできます。これに対する答えは、実際にはFortranです。Fortranコンパイラには、certianの利点があります。

  • Fortranは、コンパイラーを使用しないことを誓った当時、アセンブリーと競合する必要があったため、スピードを重視して設計されました。Cは柔軟に設計されています。
  • Fortranのニッチは非常に処理されています。このドメインでは、コードが十分に速くなることはありません。したがって、言語を効率的に保つために常に多くのプレッシャーがありました。
  • コンパイラーの最適化に関する研究のほとんどは、Fortranの数値処理コードの高速化に関心のある人々によって行われるため、Fortranコードの最適化は、他のコンパイル済み言語の最適化よりもよく知られている問題であり、新しい革新がFortranコンパイラーに最初に現れます。
  • Biggie:CはFortranよりもはるかに多くのポインターの使用を推奨しています。これにより、Cプログラムのデータ項目の潜在的なスコープが大幅に増加し、最適化がはるかに困難になります。また、Adaはこの領域ではCよりも優れており、一般的に見られるFortran77よりもはるかに新しいOO言語です。Cよりも高速なコードを生成できるオブジェクト指向言語が必要な場合は、これがオプションです。
  • 繰り返しになりますが、その数の多いニッチにより、Fortranコンパイラーの顧客は、Cコンパイラーの顧客よりも最適化を重視する傾向があります。

ただし、Cコンパイラーの最適化に多大な労力を費やして、プラットフォームのFortranコンパイラーよりも優れたコードを生成することを妨げるものは何もありません。実際、Cコンパイラが生み出した売り上げの増加により、このシナリオは実現可能になっています


4
同意する。そして、50年代後半から60年代前半にFortranが導入されたとき(最初の高級言語でした)、多くの人がそれがどれほど効率的であるかについて懐疑的でした。したがって、その開発者は、Fortranが効率的で有用であることを証明し、彼らの要点を証明するためだけに「最適化して死ぬ」ことを試みなければなりませんでした。Cはずっと後に(70年代前半から半ばまで)来て、いわば証明するものは何もありませんでした。しかし、このときまでに多くのFortranコードが作成されていたため、科学コミュニティはそれに固執し、現在もそうです。私はFortranをプログラミングしていませんが、C ++からFortranサブルーチンを呼び出すようにリンクする方法を学びました。
Olumide

3
コンパイラの最適化に関する研究は、あなたが考えているよりも多様です。たとえば、LISP実装の歴史は、Fortran(挑戦するデフォルトの候補のままである)よりも速く数値を処理することで成功を収めてきました。また、コンパイラーの最適化の大部分はコンパイラーの中間表現を対象にしています。つまり、セマンティクスの違い(エイリアスなど)は、特定のクラスのすべてのプログラミング言語に適用されます。
どこ男ません

2
アイデアは何度も繰り返されますが、プログラミング言語の設計に固有の効率に影響がないと言うのは少し不誠実です。一部のプログラミング言語機能は、コンパイル時に利用可能な情報を制限するため、必ずしも非効率になります。
Praxeolitic 2015

@Praxeolitic-それはまったく正しいです(そのため、私はそのようなことを言わなかったことを嬉しく思います)。
2015年

@TED正直なところ、数か月後にここに戻ってきたので、なぜあなたの回答にコメントを残したのかわかりません。多分私はそれを別の場所に残すつもりですか?XP
Praxeolitic 2015年

22

FortranがCとは異なり、より高速である可能性のある別の項目があります。FortranはCよりも優れた最適化ルールを備えています。Fortranでは、式の評価順序が定義されていないため、コンパイラーはそれを最適化できます。特定の順序を強制したい場合は、括弧を使用する必要があります。Cでは順序ははるかに厳しくなっていますが、「-fast」オプションを使用すると、それらはより緩和され、「(...)」も無視されます。Fortranには、真ん中にうまく行く方法があると思います。(まあ、IEEEは、特定の評価順序の変更でオーバーフローが発生しないようにする必要があるため、ライブをより困難にします。オーバーフローは無視するか、評価を妨げる必要があります)。

よりスマートなルールのもう1つの領域は、複素数です。C 99までにCが持っていただけでなく、それらを管理するルールもFortranで優れています。gfortranのFortranライブラリは部分的にCで記述されていますが、Fortranセマンティクスを実装しているため、GCCはオプションを取得しました(これは「通常の」Cプログラムでも使用できます)。

-fcx-fortran-rules複雑な乗算と除算はFortranの規則に従います。範囲の縮小は複素数除算の一部として行われますが、複素数の乗算または除算の結果が "NaN + I * NaN"であるかどうかのチェックは行われず、その場合は状況を救うための試みが行われます。

上記のエイリアスルールは、もう1つのボーナスであり、少なくとも原則として、コンパイラーのオプティマイザーによって適切に考慮される場合、配列全体の操作はより高速なコードを導くことができます。反対に、特定の操作には時間がかかる、たとえば、割り当て可能な配列への割り当てを行う場合、多くのチェックが必要です(再割り当て?[Fortran 2003の機能]、配列のストライドなど)。単純な操作は舞台裏でより複雑です-そのため遅くなりますが、言語はより強力になります。一方、境界とストライドが柔軟な配列演算を使用すると、コードを簡単に記述できます。通常、コンパイラーはユーザーよりもコードを最適化します。

全体として、CとFortranはどちらもほぼ同じくらい高速だと思います。どちらを優先するか、またはFortranの配列全体の操作を使用して移植性を向上させるか、Cのシステムライブラリとグラフィカルユーザーインターフェイスライブラリへのインターフェイスを改善するかを選択する必要があります。


Nan + INanの場合に意味のある「救出」とは何ですか?無限大とNaNの違いは、無限大が署名されていることです。複雑な無限大を伴う演算では混乱した符号が生成され、NaNが生成されます。複素数がそうでなければならない理由はわかりません。(DBL_MAX、DBL_MAX)を(2,2)で乗算し、結果を2乗してから、その結果を2乗する場合、オーバーフローがない場合の結果の符号は何ですか?代わりにそれを(1.001、DBL_MAX)倍するものは何ですか?(NaN、NaN)は正解であり、無限大とNaNの任意の組み合わせは無意味だと思います。
スーパーキャット2018年

14

FortranとC の言語については、特定の目的で一方を他方よりも速くするものは何もありません。これらの各言語の特定のコンパイラについては、特定のタスクを他のタスクよりも有利にするものがあります。

長年、Fortranコンパイラーが存在し、数値ルーチンにブラックマジックをもたらし、多くの重要な計算をめちゃくちゃに高速化しました。最近のCコンパイラも同様にできませんでした。その結果、Fortranで多くの優れたコードライブラリが成長しました。これらの十分にテストされた成熟した素晴らしいライブラリーを使用したい場合は、Fortranコンパイラーを使用してください。

私の非公式な観察によると、最近の人々は重い計算を古い言語でコーディングし、時間がかかると、安価な計算クラスタで時間を見つけていることがわかります。ムーアの法則は私たち全員をばかにします。


11
これはほとんど更新されました。問題は、Fortranにいくつかの固有の利点があることです。しかし、あなたが見るべき重要なことは言語ではなくコンパイラーであるということはかなり正しいです。
TED

14

Fortran、C、およびC ++の速度を、netlibの古典的なLevine-Callahan-Dongarraベンチマークと比較します。OpenMPでの複数言語バージョンは http://sites.google.com/site/tprincesite/levine-callahan-dongarra-vectors です。Cは自動翻訳と特定の制限とプラグマの挿入で始まったため、醜いですコンパイラ。C ++は、該当する場合はSTLテンプレートを備えた単なるCです。私の見解では、STLは保守性を向上させるかどうかに関しては混合されたバッグです。

例はインライン化への依存度がほとんどない従来のFortranプラクティスに基づいているため、最適化をどの程度改善するかを確認するための自動化関数インラインの最小限の実行のみがあります。

最も広く使用されているC / C ++コンパイラには、これらのベンチマークが大きく依存する自動ベクトル化がありません。

これの直前に投稿された投稿について、Fortranで括弧を使用して評価のより高速またはより正確な順序を指示する例がいくつかあります。既知のCコンパイラには、より重要な最適化を無効にせずに括弧を監視するオプションがありません。


エイリアスの問題を解決するには、醜い翻訳が必要です。ポインターとして実装されたbyref変数をレジスター最適化できることを伝えるために、コンパイラーにモック変数を与える必要があります。
デビッド

12

私は趣味のプログラマーであり、私は両方の言語で「平均的」です。C(またはC ++)コードよりも高速なFortranコードを書く方が簡単だと思います。FortranとCはどちらも(今日の標準では)「歴史的な」言語であり、頻繁に使用されており、無料で商用のコンパイラを十分にサポートしています。

それが歴史的事実であるかどうかはわかりませんが、Fortranは並列化/分散/ベクトル化/ whatever-many-cores-izedするように構築されているように感じます。そして今日、私たちが速度について話しているとき、それはほとんど「標準的な指標」です:「それはスケールしますか?」

純粋なCPU処理には、Fortranが大好きです。IOに関連することなら、Cを使用する方が簡単だと思います(どちらにしても難しいです)。

もちろん、並列計算を多用するコードの場合は、おそらくGPUを使用したいと思うでしょう。CとFortranのどちらにも、多かれ少なかれよく統合されたCUDA / OpenCLインターフェイス(そして現在はOpenACC)がたくさんあります。

私の適度に客観的な答えは:両方の言語を同等または十分に理解している場合、並列/分散コードをCよりもFortranで書く方が簡単であるため、Fortranの方が速いと思います(「フリーフォーム」のFortranを記述できることを理解したら、厳密なF77コードではありません)

1つ目の答えが気に入らないので、私に反対票を投じてくれる方のための2つ目の答えは次のとおりです。どちらの言語にも、高性能コードを記述するために必要な機能があります。つまり、実装するアルゴリズム(CPU集中型?IO集中型?メモリ集中型?)、ハードウェア(単一CPU?マルチコア?分散型スーパーコンピューター?GPGPU?FPGA?)、スキル、そして最終的にはコンパイラー自体に依存します。CとFortranの両方に素晴らしいコンパイラがあります。(私はFortranコンパイラーの高度さに驚いていますが、Cコンパイラーもそうです)。

PS:Fortran GUIライブラリについて言うべき悪いことがたくさんあるので、特にライブラリを除外してよかったです。:)


11

数年間、FORTRANとCを使って広範な数学を行っていました。私自身の経験から、FORTRANはCよりも実際には優れているが、その速度ではないことがわかります(適切なコーディングスタイルを使用することで、CをFORTRANと同じくらい高速に実行できます)。優れた並列化。私の意見では、FORTRANは非常に扱いにくいものであり、その利点はその欠点を取り消すには十分ではないため、現在はC + GSLを使用して計算を行っています。


10

FortranとCの間の速度の違いは、コンパイラーの最適化と特定のコンパイラーによって使用される基礎となる数学ライブラリーの関数になります。Cよりも速くなるFortranに固有のものはありません。

とにかく、優れたプログラマーはFortranを任意の言語で作成できます。


@スコット・クローソン:-1になりましたが、理由はわかりません。これを改善するために+1しました。ただし、考慮に入れるべきことは、Fortranが多くの親よりも長く存在していたことです。コンパイラ出力の最適化に費やされた多くの時間:D
user7116

同意する。非常によく似た回答を並行して投稿したところです。
トールジェフ

Cのポインターエイリアスの問題は他の人によって提起されましたが、プログラマーが最新のコンパイラーでそれを処理するために使用できるいくつかの方法があるので、私はまだ同意します。
トールジェフ

1
@Kluge:「Cよりも速くなるFortranの本質的なものは何もない」。ポインターのエイリアシング、複合値をレジスターに返す、組み込みの上位レベルの数値構造...
Jon Harrop

9

FortanがCよりもはるかに高速であるとは聞いていませんが、場合によっては高速であると考えられます。そして重要なのは、存在する言語機能ではなく、(通常)存在しない言語機能です。

Cポインターがその例です。Cポインターはほとんどどこでも使用されますが、ポインターの問題は、コンパイラーが通常、同じ配列の異なる部分を指しているかどうかを判断できないことです。

たとえば、次のようなstrcpyルーチンを作成したとします。

strcpy(char *d, const char* s)
{
  while(*d++ = *s++);
}

コンパイラーは、dとsが重複する配列である可能性があるという想定の下で機能する必要があります。そのため、配列がオーバーラップする場合に異なる結果を生成する最適化を実行できません。ご想像のとおり、これにより実行できる最適化の種類が大幅に制限されます。

[C99には、ポインターが重複しないことをコンパイラーに明示的に伝える「restrict」キーワードがあることに注意してください。また、Fortranにもポインターがあり、セマンティクスはCのものとは異なりますが、ポインターはCのように普遍的ではありません。]

しかし、C対Fortranの問題に戻ると、Fortranコンパイラーは、(単純に書かれた)Cプログラムでは不可能ないくつかの最適化を実行できると考えられます。だから私はその主張にあまり驚かないでしょう。ただし、パフォーマンスの違いはそれほど大きくないと思います。[〜5-10%]


9

すばやく簡単: どちらも同じくらい高速ですが、Fortranの方が簡単です。 結局のところ、本当に速いものはアルゴリズムに依存しますが、とにかく速度の違いはほとんどありません。これは、2015年にドイツのシュトゥットガルトにある高性能コンピューティングセンターで行われたFortranワークショップで学んだことです。私はFortranとCの両方で作業しており、この意見を共有しています。

説明:

Cは、オペレーティングシステムを作成するために設計されました。したがって、高パフォーマンスのコードを書くのに必要以上の自由があります。一般にこれは問題ありませんが、注意深くプログラミングしないと、コードの速度が低下します。

Fortranは科学的プログラミング用に設計されました。このため、これはFortranの主な目的であるため、構文的に高速なコードの記述をサポートします。世論とは対照的に、Fortranは古いプログラミング言語ではありません。最新の標準は2010年であり、新しいコンパイラーは定期的に公開されています。これは、最も高性能なコードがFortranで記述されているためです。Fortranはさらに、(Cプラグマの)コンパイラ指令として最新の機能をサポートします。

例: 関数(fortran:サブルーチン)への入力引数として大きな構造体を指定したいとします。関数内では、引数は変更されません。

Cは、参照による呼び出しと値による呼び出しの両方をサポートしています。これは便利な機能です。私たちの場合、プログラマーは誤って値渡しを使用する可能性があります。最初に構造体をメモリ内にコピーする必要があるため、これにより処理速度が大幅に低下します。

Fortranは参照による呼び出しのみで機能します。これにより、プログラマーが値による呼び出し操作を本当に必要とする場合、プログラマーは手動で構造体をコピーする必要があります。私たちの場合、fortranは参照による呼び出しを使用してCバージョンと同じくらい高速になります。


Cでネイティブの並列アプリケーションを作成できますか(ライブラリを呼び出さないという意味ですか)。いいえ。Fortranでネイティブ並列アプリケーションを作成できますか?はい、いくつかの方法があります。エルゴ、Fortranは「高速」です。ただし、公平を期すために、あなたがコメントを書いた2010年には、Fortranの並列do機能とco-array機能のサポートは、現在ほど広くはありませんでした。
Mali Remorker

@MaliRemorker彼は2010年に、2016年にこれを書いた
コワルスキー

並列プロセスを作成するオーバーヘッドは、私の意見では、プログラミング言語が「高速」と呼ばれるのに最も関連する要素ではありません。より適切なのは、パフォーマンスの低いコードの平和のような、実用的な考慮事項です。したがって、一度(並列プロセスを作成するときに)時間を節約し、後で複数のコアでそれを無駄にしても、何の助けにもなりません。「高速」という用語は、非並列コードも考慮する必要があります。このため、私の主張に反論することはできません。多分あなたのコメントは独立した答えとしてのメンでしたか?
Markus Dutschke

8

一般に、FORTRANはCよりも低速です。Cはハードウェアレベルのポインターを使用できるため、プログラマーは手動で最適化できます。FORTRAN(ほとんどの場合)は、ハードウェアのメモリアドレッシングハックにアクセスできません。(VAX FORTRANは別の話です。)私は1970年代からFORTRANをオンとオフで使用しています。(本当に。)

しかし、90年代に始まるFORTRANは、本質的に並列アルゴリズムに最適化することができる特定の言語コンストラクト含むように進化していることができ、実際に、マルチコアプロセッサ上で悲鳴を。たとえば、自動ベクトル化では、複数のプロセッサがデータのベクトルの各要素を同時に処理できます。16プロセッサ-16要素ベクトル-処理にかかる時間は1/16です。

Cでは、独自のスレッドを管理し、マルチプロセッシング用にアルゴリズムを注意深く設計し、一連のAPI呼び出しを使用して、並列処理が適切に行われるようにする必要があります。

FORTRANでは、多重処理のためにアルゴリズムを注意深く設計するだけで済みます。コンパイラとランタイムは、残りを処理できます。

High Performance Fortranについては少し読むことができますが、多くのデッドリンクが見つかります。並列プログラミング(OpenMP.orgなど)と、FORTRANがそれをどのようにサポートするかについて読んでおくとよいでしょう。


6
@ S.Lott:私がここに持っているほとんどのコードに対してFortranが単純にFortranと同じくらい上手く機能するために、どれほどひどいCコードが必要なのか想像できませんでした...そして私はCプログラマーです。Fortranのより単純なコードからパフォーマンスが向上します。あなたや私が反例を見つけることができなかったというわけではありません。:D
user7116 2008

2
@Greg Rogers:私ではなく、Fortranベクトル化の人々に問題を取り上げなければならないでしょう。私は読んだことを報告しているだけです。 polyhedron.com/absoftlinux
S.Lott

2
-1 //「一般に、FORTRANはCよりも低速です。これはほとんどすべての場合に当てはまります。」どうして?// FortranとCでのマルチスレッドの使いやすさに基づく引数は、パフォーマンスについては何も言っていません。
steabert

4
@ S.Lott:「マルチスレッドはパフォーマンスのためにのみ存在します」。いや、違う。
Jon Harrop

4
@ S.Lott:「ハードウェアレベルでのCのポインターの使用により、CはFortranよりも高速になります。」エラー、いいえ
Jon Harrop、2012年

5

より高速なコードは実際には言語に依存していません。コンパイラなので、「。exe」内に結び付けられた肥大化した低速で冗長なオブジェクトコードを生成するms-vb「コンパイラ」を見ることができますが、powerBasicはあまりにも方法を生成しますより良いコード。CおよびC ++コンパイラーによって作成されたオブジェクトコードは、いくつかのフェーズ(少なくとも2つ)で生成されますが、ほとんどのFortranコンパイラーには、高レベルの最適化を含む少なくとも5つのフェーズがあるため、Fortranは常に高度に最適化されたコードを生成する機能を備えています。したがって、最後に求めるのは言語ではなくコンパイラです。私が知っている最高のコンパイラは、インテルFortranコンパイラです。これは、LinuxとWindowsで入手でき、VSをIDEとして使用できるためです。 OpenWatcomでいつでも中継できる安価なコンパイラー。

これに関する詳細情報:http : //ed-thelen.org/1401Project/1401-IBM-Systems-Journal-FORTRAN.html


3

FortranのI / Oルーチンは優れています。たとえば、暗黙のdo機能は、Cの標準ライブラリでは対応できない柔軟性を提供します。

Fortranコンパイラーは、関連するより複雑な構文を直接処理します。そのような構文は引数を渡す形式に簡単に変換できないため、Cは効率的に実装できません。


1
I / OでFortranがCを上回ることを示すベンチマークはありますか?
ジェフ

3

最新の標準とコンパイラを使用して、いいえ!

コンパイラーがエイリアシングについて心配する必要がないため、FORTRANの方が高速である(したがって、最適化中にさらに多くの仮定を行うことができる)ことをここに言う人々もいます。しかし、これはC99(私が思う)標準以来、restrictキーワードを含めてCで扱われてきました。これは基本的にコンパイラーに、giveスコープ内ではポインターがエイリアスされないことを伝えます。さらに、Cは適切なポインター演算を可能にします。エイリアスのようなものは、パフォーマンスとリソース割り当ての点で非常に役立ちます。FORTRANの最近のバージョンでは、「適切な」ポインターの使用が可能になると思いますが。

最近の実装では、Cは一般にFORTRANよりも優れています(ただし非常に高速です)。

http://benchmarksgame.alioth.debian.org/u64q/fortran.html

編集:

これに対する公平な批判は、ベンチマークが偏っている可能性があることのようです。以下は、結果をより多くのコンテキストに置く別のソース(Cに関連)です。

http://julialang.org/benchmarks/

ほとんどの場合、Cは通常Fortranよりも優れていることがわかります(ここでも、ここで適用される以下の批評を参照してください)。他の人が述べたように、ベンチマークは、他の言語よりも1つの言語を支持するために簡単にロードできる不正確な科学です。しかし、FortranとCが同様のパフォーマンスをどのように発揮するかを説明します。


4
まだFORTRANであると想定している投稿から、Fortranについて何かを信じるのはばかでしょう。それは25年以上前に変わりました。これらのテストでは言語を比較できません。IntelとGCCの両方にCとFortranの両方のコンパイラーがありますが、異なるベンダーのコンパイラーを使用しているためです。したがって、これらの比較は価値がありません。
ウラジミールF

2

Fortranは、配列、特に多次元配列を非常に便利に処理できます。Fortranでの多次元配列の要素のスライスは、C / C ++の場合よりもはるかに簡単です。C ++には、BoostやEigenなどの機能を実行できるライブラリーがありますが、それらはすべて外部ライブラリーの後にあります。Fortranでは、これらの関数は組み込みです。

Fortranが開発においてより高速であるか、より便利であるかは、主に終了する必要のあるジョブに依存します。地球物理学の科学計算を行う人として、私はほとんどの計算をFortranで行いました(つまり、現代のFortran、> = F90)。


1
また、Fortranがより高速であるかどうかも、使用するコンパイラー(重要です!)、計算ジョブでコードに適切な並列化を適用するかどうか、およびコードの記述方法によって異なります。
カイ

1

これは、コンパイラの品質など、他の何よりも重要になるため、多少主観的ではありません。ただし、より直接的に質問に答えるには、言語/コンパイラの観点から言えば、CよりもFortranが本質的にCよりも高速または優れていることはありません。重い演算を実行している場合は、コンパイラーの品質、各言語のプログラマーのスキル、およびこれらの操作をサポートする組み込みの数学サポート・ライブラリーが、特定の実装でどちらがより高速になるかを最終的に決定します。

編集:@Nilsなどの他の人々は、Cでのポインターの使用の違いと、Cで最も単純な実装をおそらく遅くするエイリアシングの可能性について良い点を挙げています。しかし、C99でそれを処理する方法があります。 、コンパイラ最適化フラグを介して、またはCが実際にどのように記述されているか。これは、@ Nilsの回答と彼の回答に続く後続のコメントで十分にカバーされています。


アルゴリズムのベンチマークテストのように聞こえます。FORTRANとCのどちらが時間がかかりませんか?私には主観的に聞こえません。おそらく何かが足りない。
S.Lott、2008

1
同意しない。言語ではなくコンパイラを比較しています。元の質問は、言語について本質的に優れている言語があるかどうかです。ここでの他の答えは、微妙な疑わしい違いのいくつかに入り込んでいますが、私はそれらがノイズの中にあることに最も同意します。
トールジェフ

これはアルゴリズムのO(n)分析ではありません。それはパフォーマンスです。パフォーマンスが架空の実装に依存しないコンセプトになる方法を見てはいけません。私は何かが欠けていると思います。
S.Lott、2009

1
-1:「Cよりも本質的に高速または優れたものにするC上のFortranについては何もありません」。いや、違う。
Jon Harrop、2012年

0

ほとんどの投稿はすでに説得力のある議論を示しているので、私はことわざの2セントを別の側面に追加します。

結局のところ、処理能力の点でFortranを速くしたり遅くしたりすることは重要ですが、Fortranで何かを開発するのに5倍の時間がかかると、

  • 純粋な数の計算とは異なるタスクに適したライブラリがありません
  • ドキュメンテーションと単体テストのためのまともなツールが欠けている
  • それは非常に表現力の低い言語であり、コードの行数が急増しています。
  • 文字列の扱いが非常に悪い
  • さまざまなコンパイラーやアーキテクチャーの間で、非常に多くの問題が発生します。
  • IO戦略が非常に悪い(シーケンシャルファイルの読み取り/書き込み。はい、ランダムアクセスファイルは存在しますが、使用されているのを見たことはありますか?)
  • それは良い開発慣行、モジュール化を奨励しません。
  • 完全に標準で完全に準拠したオープンソースコンパイラの実質的な欠如(gfortranとg95の両方がすべてをサポートしているわけではありません)
  • Cとの相互運用性が非常に低い(マングリング:1つのアンダースコア、2つのアンダースコア、アンダースコアなし、一般に1つのアンダースコアが別のアンダースコアがある場合は2つ。COMMONブロックを掘り下げないでください...)

その後、問題は無関係です。何かが遅い場合、ほとんどの場合、特定の制限を超えて改善することはできません。もっと速くしたい場合は、アルゴリズムを変更してください。結局、コンピュータの時間は安いです。人間の時間ではありません。人間の時間を短縮する選択を大切にします。コンピュータの時間が増加する場合は、とにかく費用対効果が高いです。


3
なぜなら、fortransの利点/欠点(他の言語との比較)の議論に追加する興味深い点を提起しますが(これには完全に同意しません)、これは質問に対する答えではありません...
steabert

@steabert:実際、私は言ったI will just add the proverbial 2 cents to a different aspect
ステファノボリーニ

1
ありきたりではない答えのために私から+1します。あなたが言ったように、Fortranはいくつかのまれなタスクで速くなるかもしれません(個人的に見ていない)。しかし、維持不可能な言語を維持するために時間を浪費すると、考えられる利点が台無しになります。
アンドレ・Bergner

10
-1。あなたはF77に関してFortranを考えているようです。これは、F90、F95、F03、および F08 に置き換えられました。
カイルカノス2013年

4
それはトレードオフの一方の側面についてのみ話しているため、反対票を投じました。ほとんどの一般的なプログラミングでは開発速度が問題になる場合がありますが、それが唯一の有効なトレードオフになるわけではありません。Fortranプログラマーは、言語のシンプルさを重視する科学者/エンジニアであることが多く(FORmula TRANslationは非常に簡単に習得して習得できます。C/ C ++はそうではありません)、優れたライブラリー(他の言語でよく使用されます)、速度(例:気象シミュレーション) Fortranでは数日かかりますが、完全に他の言語で記述した場合は数か月かかります)。
BraveNewCurrency 2013年

-3

Fortranは伝統的に-fp:strictなどのオプションを設定しません(そのためには、f2003標準の一部であるUSE IEEE_arithmeticの一部の機能を有効にする必要があります)。インテルC ++も-fp:strictをデフォルトとして設定していませんが、たとえばERRNO処理に必要であり、他のC ++コンパイラーはERRNOをオフにしたり、simdリダクションなどの最適化を得たりするのに便利ではありません。gccとg ++では、危険な組み合わせ-O3 -ffast-math -fopenmp -march = nativeを使用しないようにMakefileを設定する必要がありました。これらの問題以外に、この相対的なパフォーマンスに関する質問は、コンパイラーとオプションの選択に関するローカルルールに依存しており、非常に不安定です。


最近のgccの更新により、Openmpとfast-mathの組み合わせによる問題が修正されました。
tim18

この答えは、ユーザーがコンパイラ自体のデフォルトフラグを理解していないことであり、言語そのものではありません。
ジェフ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.