CはC ++よりも著しく高速です[クローズ]


83

私が理解している限り、すべてのスクリプト言語とコア科学プログラムは通常Cで書かれています。これにより、実装が煩雑になりますが、ポイントにまっすぐになります。

これらの人々がパフォーマンスを最大化したいと思っていることは理解していますが、C文字列とC構造体を使用することとC ++クラスを使用することには本当の違いがあります。C ++は、仮想関数を除いて同じように機能するようですが、クラス関数を1回格納し、そのクラスのすべてのインスタンスがその1つの関数を呼び出します。

Cを高速化する理由と、最速でなければならないpythonやsqliteなどのプロジェクトの顕著な違いは何ですか?


9
「あなたが直面している実際の問題に基づいて、実用的で答えられる質問だけをするべきです。」--stackoverflowFAQ。
RedGrittyBrick 2011

2
「どの言語でもうまく書かれたコードは、他の言語でうまく書かれていないコードよりも常に優れています。」
Kerrek SB 2011

5
@ Will-いいえ。「ある言語は他の言語よりも速いですか」と答えることはできません。言語は高速ではなく、その実装だけです。「ある言語のX実装は、別の言語のY実装よりも高速ですか?」プロファイリングで答えることができますが、何をプロファイリングしますか?言語の実装はさまざまな分野で高速または低速になる可能性があり、それらすべてをテストすることは間違いなく不可能です。より良い質問は、「言語設計者がY言語ではなくX言語を選択するのはなぜですか?」です。それには明確な答えがあり(さまざまな言語設計者によって与えられた理論的根拠)、役立つ可能性が高くなります。
クリス・ルッツ2011

3
CとC ++の同じコードは、通常、まったく同じ速度で実行する必要があります。ただし、エイリアスルールが異なるなどの理由でセマンティクスが異なるコードは例外です。CイディオムとC ++イディオムの違いは異なります。CまたはC ++でベストプラクティスのCイディオムを使用してコードを作成する場合、通常、ベストプラクティスのC ++イディオムを使用して作成された同様の機能よりもはるかに軽量で高速です(処理する障害ケースが少なくなります)(作成するかどうかに関係なく)。 CまたはC ++)ですが、おそらく書くのにもっと多くの作業が必要になります。
R .. GitHub STOP HELPING ICE 2011

9
Cは、C ++よりも全体の学習が著しく高速です;)
fredoverflow 2011

回答:


68

C ++は、科学プログラムによく使用されます。Cの人気はその領域で衰えているかもしれません。Fortranは、「低水準」言語として引き続き人気があります。

C ++では、「使用した分だけ支払う」。したがって、Cより遅くなることはありません。特に科学プログラムの場合、式テンプレートを使用すると、テンプレートエンジンを使用してカスタム最適化を実行し、プログラムのセマンティクスを処理できます。

PythonなどのプロジェクトでCが好まれる理由は、読むのが混乱しにくい傾向があるため、大きなコードベースは、より多くの貢献者のプールにアクセスしやすくなるからです。

SQLiteには、実行可能コードのサイズを小さくする必要がありますが、Cにはわずかなエッジがあります。C ++を賢明に使用することで、組み込みアプリケーションでの使用が可能になりますが、不要な言語機能が忍び寄る恐れがあるため、あまり一般的ではありません。


10
C ++は名前マングリングを行いますが、Cはそうではないことに注意してください。これにより、他の言語がCと直接インターフェースすることが容易になります。(swigは、C ++ライブラリへのPythonラッパーを作成する前に、実際にC ++コードへのCインターフェイスを構築します。)
Sam P

8
@SamP C ++には、名前マングリングを無効にする機能がありますextern "C"。SwigはたまたまCを共通語として使用していますが、そのラッパーをC ++のC互換サブセット内に実装し、Cコンパイラーを呼び出すことはできません。
ポテトスワッター2015

「SQLiteには実行可能コードのサイズを小さくする必要がありますが、Cにはわずかなエッジがあります。」慣用的なC ++で記述されたSQLiteは、バイナリ単位で大きくなったり、Cの実装よりも遅くなるとは思いません。それは確かにはるかに少ないC ++コードであり、オプションのLINQとコンパイル時クエリの事前最適化とコンパイルを提供できます。Cはそのためのコードジェネレーターを必要とするため、SQLITEではクエリをプリコンパイルできません。C ++ SQLITEを使用すると、VMコードを介在させることなく、範囲を指定してレコードを反復できます。これにより、CSQLITEは比較的ペースが速いように見えます。残念...
クバはモニカ忘れていない

実際、典型的なサイズ重視の組み込みSQLITEアプリケーションには固定クエリセットがあり、データベースは固定スキーマを使用してフラッシュからメモリマップされ、SQLインタープリターとVMは、他の多くのコードと同様に自重です。「raw」Cを使用してクエリを記述し、SQLITEで低レベルのページアクセスを使用していくつかの実験を行いました。特定のアプリケーションでは、SQLITEコードの85%を多かれ少なかれ破棄できました。したがって、どちらかといえば、SQLITEはC ++を活用しないことで大きな時間を失いますが、C ++が利用できないプラットフォームを対象としており、クエリ用のCコードジェネレーターを実装していません。
クバはモニカを忘れていません

@UnslanderMonica 1. C ++バイナリには例外処理テーブルがあり、空の場合でもマージンが追加されます。2.SQLiteはバイトコードベースです。C ++でのコンパイル時のクエリ最適化は、ポインターを使用できないconstexpr関数での解析と分析を意味します。これは、製品がSQLiteではなくなるようなアーキテクチャの変更を示唆しています。3.バイトコードを保存し、アプリケーションとライブラリのバイナリからテキストとパーサーを取り除く方法はありませんか?4.パーサーフリーまたは「ヘッドレス」SQLiteは、C ++ヘッダーのみのバイトコードジェネレーター/オプティマイザーとインターフェイスできます。
ポテトスワッター

27

その理由は、相互運用性ほどパフォーマンスに関係しているとは思いません。C ++言語はC言語よりも複雑ですが、パフォーマンスの観点からは、どちらの方法でも顕著な違いはないはずです。一部のC ++構造は、同等のCよりも高速です(std::sortより高速ですqsort)。おそらく、その逆の良い例があります。

編集:相互運用性の面で...

基本的に、C ++標準では、異なるコンパイラ/バージョンで作成されたバイナリ間の相互運用を容易にするために必要となる可能性のあるもののいくつかは定義されていません。ここで最も注目すべき問題は、バイナリ内のシンボルの命名規則です。Cでは、言語はコード内の各シンボルからバイナリシンボル名への単一のマッピングを定義します。と呼ばれる関数my_functionは、と呼ばれるバイナリにシンボルを作成しますmy_function。一方、関数のオーバーロードなどの機能のために、C ++関数の名前をマングルする必要があります(バイナリのさまざまな関数シンボルに変換され、引数の型と戻り型をエンコードします)。標準では、マングリングの実行方法は定義されていません。つまり、C ++の同じ関数は、コンパイラーに応じて異なるシンボルにコンパイルできます(extern "C"C ++の関数のC相互運用性を強制するために使用されている場合を除く)。

結局のところ、スクリプト言語とネイティブコード間のインターフェイスは、内部での実装方法の詳細がC / C ++ /その他のネイティブ言語であっても、とにかくCインターフェイスである必要があります。

(私は意図的に言語の炎上戦争に参加したくありません。C++は本当に強力ですが、Cよりもはるかに複雑な言語であるため少し怖いです。単純に見えるものが影響を与える可能性があります。パフォーマンス)


2
現代の慣用的なC ++には、インライン化、RVO、定数畳み込みなどを最大限に活用するためにインテリジェントなコンパイラが必要であると自信を持って言えると思います。これにより、重量のあるC ++構造がまったく目立たなくなる可能性があります。マシンレベルですが、C ++ではCよりも優れたコンパイラの方がはるかに重要です
。– Kerrek SB 2011

@Kerrek SB:ほとんどの最新のC ++コンパイラ(最新はここ数年を意味します)は、慣用的なC ++構造の識別と最適化に非常に優れています。これstd::sortはそのような例の1つstd::lessです。デフォルトで使用されるファンクターは同等のC関数よりも効率が悪くありませんが、私が知っているすべてのコンパイラーはそれをインライン化し(インライン化に使用できるテンプレートであるため)、compareファンクターへのすべての関数呼び出しを削除します。
デビッド・ロドリゲス-ドリビア2011

おかしなことに、Electronic ArtsのEASTLライブラリは、GCCのインライン化が不十分である(そしてMSVCの方がはるかに優れている)ため、標準ライブラリで最適化されていない関数呼び出しが多すぎると主張することで部分的に正当化されます。EASTLでは、これに対抗するために使用する指示が少なくなります。その推論が今日どれほどうまく維持されているか誰が知っていますか。
Kerrek SB 2011

13

Bjarneが[D&E]で述べたように、有効性はC ++の主な目標の1つです。したがって、C ++は、プログラマーが前述の仮想関数やrtt情報などの「追加の」関数を使用する場合にのみ遅くなります。

ですから、それは心理的な理由だと思います。Cは、「遅い」C ++機能を許可しないために使用されます。


9

言語は本質的に速くも遅くもありません、インタプリタとコンパイラは多かれ少なかれ効率的かもしれません。

それに加えて、高級言語は通常実行時間のコストがかかる抽象化レイヤーを提供します。それらを使用していない場合、コンパイラはそれらを取り除くのに十分賢いかもしれませんが、言語のセマンティクスがそれを安全に行うことができない場合、それは不可能かもしれません...そしてあなたがそれらを必要とするならば、あなた自身でそれらを実装してください低レベルの言語では、「遅い」言語を使用するよりもおそらく遅くなります。


25
本当にひどいコンパイル済みコードを書かない限り、スクリプト言語はコンパイルされた言語よりも継承的に遅くなります
Will03uk 2011

2
@ Will03uk-通常スクリプト言語用のコンパイラを作成することを妨げるものは何ですか?
クリス・ルッツ2011

6
@Chrisの場合、スクリプト言語ではありません。スクリプト言語の意味するところは、それが解釈されるか、バイトコードでコンパイルされるということです。コンパイルしたら、コンパイルされた言語ではありません
Will03uk 2011

1
これは完全な真実ではありません。言語セマンティクスは、オプティマイザーが利用できる情報を決定し、プログラム全体の分析を実行せずに安全に行うことができる仮定を決定するため、重要です。restrict適切な例:Cまたはluajitのキーワード-後者は、Mikeが賢い人であるという理由だけでなく、Luaのセマンティクスがかなりクリーンであるという理由だけで(JavaScriptなどと比較して)動的言語の他のすべてのVMを吹き飛ばしません
クリストフ

1
@Christoph私が言おうとしているのは、特効薬はないということです。あなたが動的ディスパッチ、仮想呼び出し、コード、またはダックタイピングのホットロードのようなものが必要な場合は、ボックスのそれを提供する「遅い」に見えるかもしれませんが、言語はより速くCの素朴な実装よりもおそらくある
FORTRAN
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.