C ++はC#よりどのくらい高速ですか?


245

それとも逆になりましたか?

私が聞いたところによると、C#がC ++よりも高速であることが証明されているいくつかの領域がありますが、私はそれを自分でテストする勇気がありませんでした。

これらの違いを詳細に説明したり、この情報の適切な場所を私に示したりできると思いました。


7
保護され、これ以上ランダムなベンチマークが投稿されないようにします。あなたがあなたのケースを作ることができると思うならば、あなたはそうするために10人の担当者を必要とするでしょう。
Robert Harvey、

2
とにかく、これはどうして意見/議論として閉じられていないのですか?まだStackOverflowを利用していませんか?(終わりを示唆するのではなく、好奇心旺盛です。私は、意見の分かれる議論に拍車をかける質問が大好きです)
Bill K

1
:それはほとんど我々はILは、CPPに変換し、そこから最適化することが可能な時代に生きていることを与えられた議論の余地の質問、だdocs.unity3d.com/Manual/IL2CPP.html
pixelpax

範囲外の配列アクセスをチェックする言語は、そうでない言語よりも性能が優れていることは決してありません。
Seva Alekseyev

@SevaAlekseyevこれを行うのは言語ではなく、コンパイラです。C ++の理由の1つは、(明らかなものを除いて)高速であることです。C++コンパイラは過去35年(これ以上ではないにしても)存在しているためです。C#コンパイラが時間の経過とともに改善するのを妨げるものは何もありません。あなたが言及するケースについては、このstackoverflow.com/questions/16713076/…
トラップ

回答:


342

JITを備えたC#やJavaなどのバイトコードベースの言語がC ++コードほど高速にできないという厳密な理由はありません。ただし、C ++コードは長い間非常に高速でしたが、現在でも多くの場合、そうです。これは主に、より高度なJIT最適化の実装が複雑であり、本当にクールなJIT最適化がたった今到着しているためです。

したがって、多くの場合、C ++の方が高速です。しかし、これは答えの一部にすぎません。C ++が実際に高速であるケースは、高度に最適化されたプログラムであり、エキスパートプログラマーがコード全体を徹底的に最適化しています。これは非常に時間がかかる(そして高価になる)だけでなく、一般的には最適化しすぎてエラーが発生します。

一方、インタプリタ言語のコードは、何もしなくても、ランタイムの新しいバージョン(.NET CLRまたはJava VM)で高速になります。そして、JITコンパイラーが実行できる多くの便利な最適化がありますが、ポインターを使用する言語ではこれは不可能です。また、ガベージコレクションは通常、手動のメモリ管理と同じかそれ以上に高速である必要があると主張する人もいます。多くの場合はそうです。通常、これらのすべてをC ++またはCで実装して実現できますが、はるかに複雑でエラーが発生しやすくなります。

ドナルドクヌースが言ったように、「時期尚早な最適化はすべての悪の根源です」。アプリケーションがほとんどの場合、パフォーマンスが非常に重要な算術演算で構成されること、そしてそれがボトルネックになること、C ++で確実に高速になること、そしてC ++が他のアプリケーションと競合しないことを確信している場合要件は、C ++のために行きます。それ以外の場合は、最初にアプリケーションを適切な言語で正しく実装することに集中し、実行速度が遅すぎる場合はパフォーマンスのボトルネックを見つけ、コードを最適化する方法を検討します。最悪の場合、外部関数インターフェイスを介してCコードを呼び出す必要があるかもしれません。そのため、下位レベルの言語で重要な部分を書くことができます。

正しいプログラムを最適化するのは比較的簡単ですが、最適化されたプログラムを修正するのははるかに難しいことに注意してください。

速度の利点の実際のパーセンテージを与えることは不可能であり、それはコードに大きく依存します。多くの場合、プログラミング言語の実装はボトルネックすらありません。http://benchmarksgame.alioth.debian.org/にあるベンチマークを大いに懐疑的に受けてください。これらは主に算術コードをテストしているため、コードにまったく似ていない可能性が高いからです。


92
<quote>インタプリタ言語のコードは、ランタイムの新しいバージョンで速くなります</ quote>より良いバージョンのコンパイラでコンパイルされたコードも速くなるためです。
マーティンヨーク

47
実際、少なくとも1つの理由があります。JITは高速である必要があり、C ++コンパイラで利用できるさまざまな高度な最適化に時間を費やす余裕がありません。
Nemanja Trifunovic

63
「しかしまた、一般的には、最適化が過剰であるためにエラーが発生します。」[必死に引用]。私は国立研究所で働いており、私たちはコードから地獄を最適化します。これは一般的にバグのあるコードにはなりません。
Todd Gamblin、

35
「正しいプログラムを最適化することは比較的簡単ですが、最適化されたプログラムを修正することははるかに困難です。」
gradbot

20
インゲ:あなたがそこに正しい軌道に乗っているかどうかわからない。はい、C#は別の言語で実装されていますが、JITコンパイラーはマシンコードを生成しているため、インタープリター型言語ではありません。したがって、そのC ++実装による制限はありません。何かにマネージャーを追加すると、本質的に速くなると思う理由がよくわかりません。
Martin Probst 2013年

202

C#は高速ではないかもしれませんが、YOU / MEは高速になります。それが私がすることの最も重要な尺度です。:)


68
ははは、このトピックに関するラリー・ウォールの良い引用があります。彼はperlについて語っていますが、言語とパフォーマンスに関するすべての議論について考えることができます。高価なコンピュータープログラマーを効率的に利用する」
Falaina '08 / 08/08

60
1.「C#はC ++よりもはるかに高速です」2.「それは真実ではあり得ない」1.「確かにできる」2.「どれだけ?」1.「通常3〜4か月」
ドミトリーS.

2
本当にあなたが使用してライブラリに依存C ++のために、C#は.NETは、ある、通常は高速ではありませんあなたは、生産話しているとき
イオンTodirel

これは、Cの代わりにPythonを使用してコードを記述できるのと同じ理由ですが、重い計算を作成すると、パフォーマンスの違いを感じることができます。
Ch3shire 2017年

それはあなたが慣れているものに依存します。C ++でのプログラミングは、C#でのプログラミングよりもはるかに高速です。基本的なタスクのためにホイールを再発明したくないので、ライブラリの知識はその大部分です。C / C ++の主な問題は、スマートポインターでかなり解決されるポインター管理でした。とは言っても、.NETやJavaが提供するようなC ++の重大なライブラリには広範なライブラリがなく、開発を大幅にスピードアップできます。これらのstdの男の子はライブラリ拡張ではなくテンプレートの改善に時間を費やしたいので、これはすぐには解決されません。
gast128

87

オレンジが5つ早くなります。むしろ:(正しい)包括的な回答はありません。C ++は静的にコンパイルされた言語です(ただし、プロファイルに基づく最適化も行われます)。C#は、JITコンパイラーによって支援されて実行されます。違いが非常に多いため、「どれだけ速く」などの質問に答えることはできません。


177
とんでもない5つのオレンジの主張を裏付ける証拠はありますか?私の実験はすべて、最大で2つのオレンジを指し、テンプレートのメタプログラミングを実行すると、マンゴーが3つ改善されます。
Alex

42
イーストでは、彼はそれを大げさなオードブルより速く鳴らしていません。
Chris

11
私の経験から、それは5.2オレンジです。しかし、これは使用するフルーツメーターに依存します。
Dio F

4
:更新、StackOverflowの自体は、このように小さいバナナ(必要以上300本のバナナが悪化)、非効率的なコメントを台無しにし、ハンドルmeta.stackexchange.com/questions/254534/...
KeksArmee

87

私はこの質問に対する受け入れられた(そして十分に賛成された)回答の一部に同意することから始めます:

実際には、JITされたコードが適切に最適化されたC ++(またはランタイムオーバーヘッドのない他の言語)プログラムよりも実行速度が遅くなる多くの理由があります

  • 実行時にコードのJITtingに費やされる計算サイクルは、プログラムの実行では使用できません。

  • JITterのホットパスは、CPUの命令とデータキャッシュのコードと競合します。パフォーマンスに関しては、キャッシュが支配的であり、C ++のようなネイティブ言語は、定義上、このタイプの競合がないことを知っています。

  • ランタイムオプティマイザのタイムバジェットは、コンパイル時オプティマイザのタイムバジェットよりも必然的にはるかに制約されます(別のコメンターが指摘したように)。

ボトムラインは:最終的に、あなたがしますほぼ確実にあなたがC#でできるよりもC ++で速い実装を作成することができます

さて、そうは言っても、タスク、問題ドメイン、ハードウェア、実装の品質、およびその他の多くの要因などの変数が多すぎるため、実際にはどれほど高速なのかを定量化することはできません。シナリオでテストを実行してパフォーマンスの違いを判断し、追加の作業と複雑さの価値があるかどうかを判断します。

これは非常に長くて複雑なトピックですが、C#のランタイムオプティマイザーは優れており、コンパイル時にC ++では利用できない特定の動的最適化を実行時に実行できることは、完全性のために言及する価値があると思います( static)オプティマイザ。これを使用しても、通常、利点はネイティブアプリケーションの法廷に深くありますが、動的オプティマイザーが上記の「ほぼ確実に」修飾子の理由です。

-

相対的なパフォーマンスに関しては、他のいくつかの回答で見た数字や議論にも不安を感じていたので、チャイムをすると同時に、上記で述べた声明をある程度サポートすると思いました。

これらのベンチマークの問題の大きな部分は、C#を記述しているかのようにC ++コードを記述できず、代表的な結果が得られることです(たとえば、C ++で数千のメモリ割り当てを実行すると、恐ろしい数が得られます)。

代わりに、もう少し慣用的なC ++コードを記述して、提供されているC#コード@Wioryと比較しました。C ++コードに加えた2つの主な変更は次のとおりです。

1)使用されるvector :: reserve()

2)キャッシュの局所性を改善するために2D配列を1Dにフラット化(連続ブロック)

C#(。NET 4.6.1)

private static void TestArray()
{
    const int rows = 5000;
    const int columns = 9000;
    DateTime t1 = System.DateTime.Now;
    double[][] arr = new double[rows][];
    for (int i = 0; i < rows; i++)
        arr[i] = new double[columns];
    DateTime t2 = System.DateTime.Now;

    Console.WriteLine(t2 - t1);

    t1 = System.DateTime.Now;
    for (int i = 0; i < rows; i++)
        for (int j = 0; j < columns; j++)
            arr[i][j] = i;
    t2 = System.DateTime.Now;

    Console.WriteLine(t2 - t1);
}

実行時間(リリース):Init:124ms、Fill:165ms

C ++ 14(Clang v3.8 / C2)

#include <iostream>
#include <vector>

auto TestSuite::ColMajorArray()
{
    constexpr size_t ROWS = 5000;
    constexpr size_t COLS = 9000;

    auto initStart = std::chrono::steady_clock::now();

    auto arr = std::vector<double>();
    arr.reserve(ROWS * COLS);

    auto initFinish = std::chrono::steady_clock::now();
    auto initTime = std::chrono::duration_cast<std::chrono::microseconds>(initFinish - initStart);

    auto fillStart = std::chrono::steady_clock::now();

    for(auto i = 0, r = 0; r < ROWS; ++r)
    {
        for (auto c = 0; c < COLS; ++c)
        {
            arr[i++] = static_cast<double>(r * c);
        }
    }

    auto fillFinish = std::chrono::steady_clock::now();
    auto fillTime = std::chrono::duration_cast<std::chrono::milliseconds>(fillFinish - fillStart);

    return std::make_pair(initTime, fillTime);
}

実行時間(リリース):Init:398µs(はい、それはマイクロ秒です)、Fill:152ms

合計実行時間:C#:289ミリ秒、C ++ 152ミリ秒(約90%高速)

観察

  • C#実装を同じ1D配列実装に変更すると、Init:40ms、Fill:171ms、Total:211ms(C ++は依然としてほぼ40%高速でした)。

  • どちらの言語でも「通常の」コードを書くよりも、C ++で「高速」なコードを設計して書く方がはるかに困難です。

  • C ++でパフォーマンスが低下するのは(おそらく)驚くほど簡単です。予約されていないベクターのパフォーマンスでそれがわかりました。そして、このような落とし穴がたくさんあります。

  • 実行時に行われているすべてのことを考えると、C#のパフォーマンスは驚くべきものです。そして、そのパフォーマンスは比較的簡単にアクセスできます。

  • C ++とC#のパフォーマンスを比較するその他の事例データ:https : //benchmarksgame.alioth.debian.org/u64q/compare.php?lang=gpp&lang2=csharpcore

つまり、C ++を使用すると、パフォーマンスをより詳細に制御できます。ポインタを使用しますか?参照?スタックメモリ?ヒープ?動的ポリモーフィズムまたは静的ポリモーフィズム(テンプレート/ CRTPを介して)を使用してvtableのランタイムオーバーヘッドを排除?あなたが...えー持つC ++では、してもらう理想的なので、あなたのソリューション最高のアドレスの問題、あなたにしているタックルこと、(およびそれ以上)を自分でこれらすべての選択を行います。

上記の簡単な例でも、パフォーマンスは大幅に改善されていますが、アクセスするにはより多くの投資が必要であることがわかります。


16
@Quonuxコメントありがとうございます。もちろん、これは「実際のプログラム」ではありません。ベンチマークの要点は、このページの他の場所で提供されているC#ベンチマークをリファクタリングすることでした。JITされたコードはネイティブよりもなんとか高速であることを示しています。
U007D 2017年

9
@Quonuxなぜあなたはそのように書く必要があるのですか?私がスタックオーバーフローを嫌うのはあなたのような人です。
Markus Knappen Johansson 2017

5
@MarkusKnappenJohansson私は悪い一日を過ごしました;)、私も人間です。ああ、「愚かな」人々がいるからといってSOを嫌わないでください:) 素敵なものを持っています。
Quonux 2017

9
完全に誤解を招くベンチマーク。C ++バージョンでは、メモリの一部を予約するだけです(そして、その操作の実行にマイクロ秒かかる方法に驚嘆します)。C#バージョンでは、5000アレイ(メモリ内のオブジェクトをインスタンス化)を作成しています。C ++はC#よりも高速ですが...違いは40%ほどではありません...現在のところ、10%未満の範囲です。あなたの例が示していることは、プログラマーが選択した言語に固執する必要があるということです(そしてあなたのプロファイルから、あなたがキャリアC ++プログラマーであることは明らかです)。C#では2D配列を行うことができますint[,] ...例に従ってください。
nikib3ro 2017

3
私が知ることができることから、C ++の例のコードは、文字通り単に事前にメモリを割り当てるだけです。PROPER C#の実装は、「List <double> arrs = new List <double>(ROWS * COLS)」と書くだけで、2次元配列を1次元形式でインデックス付けするために必要なメモリを割り当てます(たとえば、C ++で行ったこと)。2次元配列を割り当てて手動でフラット化する理由はまったくありません-事前テストでの大量の反復がパフォーマンス低下の原因です。オーバーヘッドはC#ではさらに増えると思いますが、かなりの量ではありません。
JDSweetBeat 2018

62

私の経験では(そして私は両方の言語で多くの作業をしてきました)、C ++と比較したC#の主な問題はメモリ消費量が高く、それを制御する良い方法を見つけていません。最終的に.NETソフトウェアの速度を低下させるのは、メモリ消費でした。

もう1つの要因は、JITコンパイラは実行時に実行されるため、高度な最適化を実行するのに時間をかけすぎることができず、時間がかかりすぎるとエンドユーザーがそれに気付くからです。一方、C ++コンパイラには、コンパイル時に最適化を行う必要があるすべての時間があります。この要素は、メモリ消費量よりもそれほど重要ではありません。


6
あるプロジェクトでは、膨大な量のデータをマイニングする必要がありました。たとえば、メモリに多数のGBを同時に保持し、そのすべてに対して高価な計算を実行しました。これには、すべての割り当てを正確に制御する必要があり、C ++がほとんど唯一の選択肢でした。C ++の場合は+1。一方、それは1つのプロジェクトにすぎず、遅いシミュレータとやり取りするシステムを作成するのにほとんどの時間を費やしており、デバッグは悪夢になる可能性があるため、他のすべてにプログラマー時間最適化言語を使用できたらよかったのですが。もの。
Bogatyr、2011

7
@IngeHenriksen:Disposeパターンはよく知っていますが、マネージメモリにはまったく役立ちません。
Nemanja Trifunovic 2013年

10
@IngeHenriksenによる破棄は、Disposeメソッドが呼び出されたことを確認するだけです。破棄によってガベージコレクションされたメモリが解放されることはありません。Disposeメソッドは、ファイルハンドルなどのアンマネージリソースのクリーンアップのみを目的としており、メモリ管理とは関係ありません。
doug65536

1
@NemanjaTrifunovic:「JITコンパイラーは、高度な最適化を行うために時間をかけすぎることができません」。時間がかかりすぎるためにJITによって行われない最適化をいくつか挙げていただけますか?
Jon Harrop、2013年

5
@ user3800527:RAMの追加が常に実現可能であったとしても(そうすることはできません-Microsoftが各MS OfficeユーザーにRAMを追加することを想像してみてください)、問題は解決しません。メモリは階層的であり、C#プログラムはC ++プログラムよりもはるかに多くのキャッシュミスを抱えています。
Nemanja Trifunovic 2016

35

C ++がまだ優位に立っている1つの特定のシナリオは、多態性の決定がコンパイル時に事前に決定できるときに発生します。

一般に、カプセル化と据え置きの意思決定は、コードをより動的にし、変化する要件への適応を容易にし、フレームワークとして使いやすくするため、良いことです。これが、C#のオブジェクト指向プログラミングが非常に生産的であり、「一般化」という用語で一般化できる理由です。残念ながら、この特定の種類の一般化は、実行時にコストがかかります。

通常、このコストは実質的ではありませんが、仮想メソッド呼び出しとオブジェクト作成のオーバーヘッドが違いをもたらす可能性があるアプリケーションがあります(特に、仮想メソッドはメソッド呼び出しのインライン化などの他の最適化を妨げるため)。これは、C ++に大きな利点があるところです。テンプレートを使用して実行時に影響を与えるが、必ずしもすべての少ない多型OOP以上ではありませんが。実際、OOPを構成するすべてのメカニズムは、テンプレート技術とコンパイル時の解決のみを使用してモデル化できます。

そのような場合(そして確かに、それらはしばしば特別な問題ドメインに制限されています)、C ++はC#および同等の言語に勝っています。


6
実際、Java VM(そしておそらく.NET)は、動的なディスパッチを回避するために非常に長くなります。基本的に、ポリモーフィムを回避する方法がある場合、VMがそれを確実に実行することができます。
マーティンプロブスト、

3
+1 C ++をほとんど知らないC#の同僚に、その重要性を理解してもらう方法でこれを説明するのは常に困難です。あなたはそれをかなりうまく説明しました。
Roman Starkov

9
@crtracy:高性能コンピューティングアプリケーションなしで賭けをします。天気予報、バイオインフォマティクス、数値シミュレーションを検討してください。これらの領域におけるC ++のパフォーマンスリードは縮小しません。これは、他のコードが同じレベルの抽象度で同等のパフォーマンスを達成できないためです。
Konrad Rudolph

5
@ジョンリンゴとオレンジ。あなたの具体的な主張は、「C#はメタプログラミングのコンテキストでC ++よりも桁違いに速い」であり、「プリコンパイルされたコードを使用すると解釈されるコードよりも桁違いに速い」ではありませんでした。私たちがそうしている間、ランタイムコード生成はコンパイル時コード生成よりも「一般的」であるというあなたの主張もまた明らかに間違っています-どちらにも長所と短所があります。コンパイル時のコード生成では、型システムを使用して静的な型安全性を提供します。ランタイムコードの生成ではそれできません(強力な型安全性提供できますが、静的な型安全性提供できません)。
Konrad Rudolph

5
@ user3800527私はあなたがこの答えの全体のポイントを逃していると思います。もちろん、カプセル化を解除し、低レベルの構造にドロップダウンすることでこれを回避できます—アセンブリを(ほとんどの)任意の言語で記述できます。C ++を(ほとんど)ユニークにし、高性能プログラミングに非常に適したものにするのは、ランタイムコストなしで高レベルの抽象化を構築できることです。したがって、プレミアムパフォーマンスを得るためにC ++でアセンブリのようなコードを記述する必要はありません。適切に記述されていれば、C ++の手書きのループと同じくらい効率的です。C#になることはありません。sort(arr, generic_comparer)
コンラッドルドルフ

20

C ++(またはそのことについてはC)では、データ構造をきめ細かく制御できます。ビットいじりたい場合は、そのオプションがあります。Java / .NETライブラリの内部データ構造を使用する大規模なマネージJavaまたは.NETアプリ(OWB、Visual Studio 2005)は、それらの手荷物を運びます。400 MBを超えるRAMとBIDSをキューブまたはETLの設計に使用するOWBデザイナーセッションも100 MBに入るのを見てきました。

予測可能なワークロード(プロセスを何度も繰り返すほとんどのベンチマークなど)では、JITは、実用的な違いがないように十分に最適化されたコードを取得できます。

大規模なアプリケーションでのIMOの違いは、コード自体が使用しているデータ構造ほどJITではありません。アプリケーションがメモリを多く使用する場合、キャッシュの使用効率が低下します。最近のCPUでのキャッシュミスは非常に高価です。CまたはC ++が実際に成功するのは、データ構造の使用を最適化してCPUキャッシュを適切に再生できる場所です。


19

グラフィックスの場合、標準のC#グラフィックスクラスは、C / C ++を介してアクセスされるGDIよりもはるかに低速です。これは言語自体とは関係ありませんが、.NETプラットフォーム全体とは関係ありませんが、グラフィックスはGDIの代替として開発者に提供されるものであり、パフォーマンスが非常に悪いので、グラフィックスを作成することすらしませんそれと。

グラフィックライブラリの速度を確認するために使用する簡単なベンチマークがあります。これは、ウィンドウにランダムな線を描画するだけです。C ++ / GDIは、10000行といまだに素晴らしく、C#/ Graphicsは、リアルタイムで1000行を実行することが困難です。


5
私はあなたの答えに興味をそそられました。安全でないコードとロックビットを使用して同じベンチマークをテストし、ランダムな線を自分で描画しましたか?今、それは見て興味深いものになるだろう。
ペデリー

2
@Pederyいいえ、私はしていません。最も基本的な方法でGDIと.NET.Graphicsを使用するだけです。「自分でランダムな線を引く」とはどういう意味ですか?
QBziZ 2012

1
次に、これをテストして、C#の高速化に関するより現実的なメトリックを取得することを検討する必要があります。テクニックの概要は次のとおり
Pedery

6
それは私たちがやりたいことではなく、フレームバッファーに別々のピクセルを自分で入れます。すべてを自分で実装しなければならない場合、API /プラットフォームをコーディングする目的は何ですか?私にとってこれは議論の余地はありません。線を描画するためにGDIのフレームバッファーに個別のピクセルを配置する必要はありませんでした。また、.NETでこれを行う予定もありません。私の見解では、現実的なメトリックを使用しましたが、.NETは遅いことが判明しました。
QBziZ

1
まあ、私はブロブ検出が何であるかについて少し考えているだけですが、1つのタイミングを述べるだけでは、まったく何も証明されません。C ++で作成したことがありますか?JavaScriptでは?そしてそれらをC#のものと比較しましたか?それ以外に、ブロブ検出で多くのグラフィックプリミティブが使用されているとは思いません。間違っている場合は私を修正しますが、それはピクセルの操作を実行する統計アルゴリズムだと思います。
QBziZ 2016

13

ガベージコレクションは、Java#をリアルタイムシステムに使用できない主な理由です。

  1. GCはいつ発生しますか?

  2. どのくらい時間がかかりますか?

これは非決定的です。


5
私はJavaの大ファンではありませんが、Javaがリアルタイム対応のGCを使用できないと言っていることは何もありません。
Zan Lynxが2010

5
注目したい場合は、多くのリアルタイムGC実装があります。(GCは研究論文であふれている領域です)
アラファンギオン2010年

FWIW、リチャードジョーンズは、とりわけ、最先端のリアルタイムGC設計をカバーする彼のガベージコレクション本の更新版を公開しました。
Jon Harrop、2011

11
これはナンセンスな議論です。Windows(およびLinux)はリアルタイムOSではありません。C ++コードは、いつでも18ミリ秒のスロットにスワップアウトできます。
Henk Holterman、2014年

2
@HenkHolterman正しいですが、常にアセンブリでブートローダーを記述し、それをアプリケーションのカーネルブートストラップに結び付けて、ハードウェアに対して直接(RT btwで)C ++アプリを実行できます。これをC#で行うことはできません。また、C#でプリコンパイルされたアセンブリを模倣するだけで、大量のCコードを使用するため、C#を使用しても意味がありません。C#は.NETフレームワークなしでは本当に役に立たないため、これらすべてを読むのはちょっとおかしいです。
zackery.fix 2016年

11

C#がC ++に匹敵するかどうかを判断する必要があり、そのためのテストプログラムをいくつか作成しました(両方の言語でVisual Studio 2005を使用)。ガベージコレクションがなく、言語(フレームワークではない)のみを考慮すると、C#は基本的にC ++と同じパフォーマンスを発揮することがわかりました。C ++の場合よりもC#の場合の方がメモリ割り当てが高速であり、キャッシュサイズの境界を超えてデータサイズが大きくなると、C#の確定性はわずかに低下します。ただし、これらすべては最終的には有料となり、ガベージコレクションが原因で、C#の非決定的なパフォーマンスヒットという形で莫大なコストがかかります。


1
C ++では、異なる割り当て方法を使用するオプションがあるため、C#でのメモリの割り当て方法(AOT?)によっては、C ++でも同じ方法(ただし、はるかに高速)で実行できます。
zackery.fix 2016年

5
@ zackery.fix .NETは、新しいオブジェクトを割り当てるためにポインターを移動するだけでよいので、ヒープ割り当てに興味深いエッジがあります。これは、ガベージコレクタを圧縮することによってのみ実現可能です。もちろん、C ++でも同じことができますが、C ++ではできません。同じ引数を使用して「C#はできますが、できないのでゴミです」と「C ++はできませんが、できるので素晴らしい」と言うのは
おかしいです

9

いつものように、それはアプリケーションに依存します。C#がごくわずかに遅い場合と、C ++が5倍または10倍速い場合、特に操作を簡単にSIMDできる場合があります。


VMのベスト場合、彼らは内蔵のJITコンパイラを持っていないため、静的にコンパイルバニラC ++プログラムは唯一の解釈を使用することができるので(例えば実行時における正規表現の読み取りに合わせて)生成されたコードの実行時のコンパイルになります。
ジョン・ハロップ

将来からの注意:.NETは広く使用されていませんが、2014年頃からSIMDとフレンドをサポートしています。
Luaan

9

私はそれがあなたが求めていたものではないことを知っていますが、C#はC ++よりも多くの場合速く書くことができます。これは商用設定では大きなボーナスです。


2
私はそれがほとんどの場合より速いと思います:)
トラップ

8

C / C ++は、大規模な配列、または(任意のサイズの)配列に対する重いループ/反復のいずれかがあるプログラムで非常に優れたパフォーマンスを発揮します。これは、C / C ++では一般にグラフィックスがはるかに高速である理由です。これは、重い配列操作がほとんどすべてのグラフィックス操作の根底にあるためです。.NETは、すべての安全性チェックのために、配列のインデックス作成操作が遅いことで有名であり、これは特に多次元配列に当てはまります(そうです、長方形のC#配列はギザギザのC#配列よりもさらに遅いです)。

C / C ++のボーナスは、直接ポインタを使い続け、Boost std::vectorやその他の高レベルのコンテナ、およびinline可能なすべての小さな関数を避けた場合に最も顕著になります。可能な限り、昔ながらのアレイを使用してください。はい。高レベルのコンテナーを回避するため、JavaまたはC#で行ったのと同じことを行うには、より多くのコード行が必要になります。動的なサイズの配列が必要な場合new T[]は、対応するdelete[]ステートメントとペアにすることを覚えておく必要があります(またはstd::unique_ptr)—速度を上げると、より慎重にコーディングする必要があります。しかし、それと引き換えに、マネージメモリ/ガベージコレクタのオーバーヘッドを取り除くことができます。オーバーヘッドは、Javaと.NETの両方で重いオブジェクト指向のプログラムの実行時間の20%以上になり、大規模なマネージドメモリアレイのインデックス作成コスト。C ++アプリは、特定の特定のケースで、いくつかの気の利いたコンパイラスイッチからも恩恵を受けることができます。

私はC、C ++、Java、C#のエキスパートプログラマです。最近、まったく同じアルゴリズムプログラムを後者の3言語で実装するまれな機会がありました。プログラムには、多くの数学および多次元配列演算がありました。これを3つの言語すべてで大幅に最適化しました。結果は、それほど厳密ではない比較で通常見られるものの典型的なものでした。JavaはC#よりも約1.3倍高速でした(ほとんどのJVMはCLRよりも最適化されています)。C#プログラムは安全なコードのみを使用したことに注意してくださいunsafe。キーワードを使用する前に、C ++でコード化することもできます。

誰かが私がC#に対して何かを持っていると思わないように、C#はおそらく私のお気に入りの言語だと言って締めくくります。これは、これまでに出会った中で最も論理的で直感的で迅速な開発言語です。プロトタイピングはすべてC#で行います。C#言語には、Javaに比べて多くの小さな微妙な利点があります(そうです、マイクロソフトがゲームに遅れをとり、間違いなくJavaをコピーすることで、Javaの欠点の多くを修正する機会があったことを知っています)。Calendar誰でもJavaのクラスに乾杯?マイクロソフトがCLRと.NET JITterを最適化するために真の努力を費やした場合、C#が真剣に引き継ぐ可能性があります。正直なところ、彼らがまだそうしていないことに驚いています。C#言語で非常に多くのことを正しく行っているので、コンパイラーの強力な最適化をフォローしてみませんか?たぶん、みんなが物乞いしたら。


3
new T[]対応するものとペアリングすることを覚えておく必要がdelete[]あります –いいえ、必要ありません。あなたのstd::unique_ptrためにそれをする必要があります。
emlai

グラフィックで何かを書いたと仮定して、なぜc#で安全なコードを書くのか、安全でないコードの使用を検討して、もう一度比較しましたか?
user3800527

7

>聞いたことから...

あなたが聞いたことを信頼できるかどうかを判断するのはあなたの難しさのようで、このサイトでの返信を評価しようとすると、その難しさが繰り返されます。

人々がここで言うことは、あなたが最初に聞いたものよりも多かれ少なかれ信頼できるものであるかどうかをどのように決定しますか?

1つの方法は、証拠を求めることです。

誰かが「C#がC ++よりも高速であることが証明されている領域がある」と主張するとき、彼らになぜそう言うのかを尋ね、測定値を見せてもらい、プログラムを見せてもらいます。時々彼らは単に間違いをしたでしょう。時には、彼らが真実であることを示すことができる何かを共有するのではなく、単に意見を表明していることに気付くでしょう。

多くの場合、情報と意見は人々が主張するもので混同され、どちらがどれであるかを整理する必要があります。たとえば、このフォーラムの返信から:

  • 「 これらは主に算術コードをテストしているため、http: //shootout.alioth.debian.org/のベンチマークを大いに懐疑的に考えてください。これはおそらくコードとまったく似ていない可能性があります。」

    「これらの大部分はテスト算術コード」の意味を本当に理解しているかどうかを自問し、次に作者が彼の主張が真実であることを実際に示しているかどうか自問してください。

  • 「これは実際には個々のプログラムがどれだけ最適化されているかに依存するため、あまり役に立たないテストです。いくつかのプログラムを4〜6倍以上高速化でき、最適化されていないプログラム間の比較はかなり明確になっています。ばかげた」

    著者が実際に「それらのいくつかを4〜6倍以上高速化した」ことを実際に示したかどうかを自問してください。これは簡単に主張できます。


私はあなたにこれ以上同意することができませんでした、そしてそれが私がこのフォーラムで尋ねた理由です...結局のところ、答えはどこかにあるはずですよね?:)
トラップ

1
はい。答えは「場合によります」です。
user49117 2008

6

「恥ずかしいほど並列」の問題の場合、C ++でIntel TBBとOpenMPを使用すると、C#とTPLで行われた同様の(純粋な計算)問題と比較して、パフォーマンスが約10倍向上しました。SIMDはC#が競合できない領域の1つですが、TPLにはかなりのオーバーヘッドがあるという印象も受けました。

そうは言っても、マルチスレッド化して結果をすばやく得ることができることがわかっているパフォーマンス重視のタスクにのみC ++を使用しています。それ以外の場合は、C#(場合によってはF#)で十分です。


5

それは本当に明確な答えがない非常に曖昧な質問です。

例えば; パフォーマンスは確かにはるかに優れているので、C#ではなくC ++で作成された3Dゲームをプレイしたい。(そして私はXNAなどを知っていますが、それは本当のところにはほど遠いものです)。

一方、前述のとおり、必要なことをすばやく実行できる言語で開発し、必要に応じて最適化する必要があります。


4
いくつか例を挙げていただけますか?C#で作成されたゲーム、遅いと感じたこと
Karl

1
インストールに付属しているサンプルアプリケーションでさえ、速度が遅く感じられました。
David The Man

9
ガベージコレクターは、C#でゲームを作成する際に大きな責任を負います。明示的なメモリ管理は、ゲーム開発にとってより簡単になります。
未来主義者、2008年

3
最新のゲームのほとんどはGPU限定です。そのようなゲームでは、ロジック(CPUで実行される)が10%遅いかどうかは問題ではありませんが、CPUではなくGPUによって制限されます。ガベージコレクターは実際の問題であり、メモリ割り当てが適切に調整されていないと、ランダムに短いフリーズが発生します。
マイケルエンティン2008年

2
@postfuturist:PCではそうではありません。ガベージコレクターは、私が出入りするのにとても良い仕事をしてくれます。しかし、Xbox 360、およびZuneの/ Windowsの-7-Phoneで、ガベージコレクタはないが、ほぼ PC上のスマートとして; 私もどちらも書いたことがありませんが、ガベージコレクター教えてくれた人は大きな問題です。
BlueRaja-ダニーPflughoeft

5

.NET言語はC ++コードと同じくらい高速になる場合がありますが、C ++コードは、.NETランタイムがGCのために一時停止する必要があるため、一時停止について非常に賢い場合でも、より一定したスループットを実現します。

したがって、一時停止なしで一貫して高速に実行する必要があるコードがある場合、ランタイムGCに非常に注意していても、.NETはある時点でレイテンシを導入します。


6
-1:これは実際には神話です。まず、大規模なデータ構造がスコープ外にあるときにRAIIがデストラクタの雪崩を引き起こす一方で、最新のGCはインクリメンタルであり、。次に、割り当てを行わないことで、.NETのGCの一時停止を実際に完全に削除できます。
Jon Harrop、2011

2
これを行うと、ほとんどのメソッドで一時オブジェクトが作成されるため、BCLの使用を控える必要があります。
Florian Doyon、2011

5
これはかなり当てはまります。GCがインクリメンタル化されたのは.net 4まででした。GCで一度に数秒間一時停止する大きなC#アプリがあります。パフォーマンスが重要なアプリにとってこれはキラーです。
ジャスティン

5
ハードウェアをプッシュする傾向があるプログラムがC ++を使用する傾向があるのには理由があります。必要に応じて、より細かく調整できます。パフォーマンスは、システムをプッシュする場合にのみ重要です。それ以外の場合は、C#またはJavaを使用して時間を節約します。
VoronoiPotato 2012年

4
キャッシュの動作を管理できない場合、最適化されたC ++コードに勝ることはできません。L1からメインメモリへのキャッシュミスにより、操作が100倍遅くなる可能性があります。
DAG 2016年

4

理論的には、サーバータイプのアプリケーションを長時間実行する場合、JITでコンパイルされた言語は、ネイティブにコンパイルされた言語よりもはるかに高速になる可能性があります。JITコンパイル済み言語は通常、最初にかなり低レベルの中間言語にコンパイルされるため、とにかくコンパイル時に多くの高レベルの最適化を実行できます。JITがアプリケーションの使用状況に関するデータを取得するにつれて、JITがコードのセクションをその場で再コンパイルし続けることができるという大きな利点があります。最も一般的なコードパスを配置して、分岐予測が可能な限り頻繁に成功できるようにします。しばしば一緒に呼び出される個別のコードブロックを再配置して、両方をキャッシュに保持することができます。内部ループの最適化により多くの労力を費やすことができます。

これが.NETまたはJREのいずれかによって行われることは疑わしいですが、私が大学にいたときに調査されていたので、これらの種類のものがすぐに現実世界に入る可能性があると考えることは不合理ではありません。


4

集中的なメモリアクセスを必要とするアプリケーション。画像操作は、通常、管理対象(C#)よりも管理対象外の環境(C ++)で作成する方が適切です。ポインター演算を使用して最適化された内部ループは、C ++での制御がはるかに簡単です。C#では、同じパフォーマンスに近づくために、安全でないコードに頼る必要がある場合があります。


4

私はvectorC ++とC#の同等のものList、および単純な2D配列でテストしました。

Visual C#/ C ++ 2010 Expressエディションを使用しています。どちらのプロジェクトもシンプルなコンソールアプリケーションです。標準(カスタム設定なし)リリースとデバッグモードでテストしました。私のPCではC#リストの実行が速く、C#では配列の初期化も速く、数学演算が遅くなります。

Intel Core2Duo P8600 @ 2.4GHz、C#-.NET 4.0を使用しています。

ベクターの実装がC#リストとは異なることは知っていますが、オブジェクトの格納に使用するコレクションをテストしたいと思っています(インデックスアクセサーを使用できます)。

もちろん、メモリをクリアする必要があります(を使用するたびに言いましょうnew)が、私はコードを単純にしたかったのです。

C ++ベクトルテスト

static void TestVector()
{
    clock_t start,finish;
    start=clock();
    vector<vector<double>> myList=vector<vector<double>>();
    int i=0;
    for( i=0; i<500; i++)
    {
        myList.push_back(vector<double>());
        for(int j=0;j<50000;j++)
            myList[i].push_back(j+i);
    }
    finish=clock();
    cout<<(finish-start)<<endl;
    cout<<(double(finish - start)/CLOCKS_PER_SEC);
}

C#リストテスト:

private static void TestVector()
{

    DateTime t1 = System.DateTime.Now;
    List<List<double>> myList = new List<List<double>>();
    int i = 0;
    for (i = 0; i < 500; i++)
    {
        myList.Add(new List<double>());
        for (int j = 0; j < 50000; j++)
            myList[i].Add(j *i);
    }
    DateTime t2 = System.DateTime.Now;
    Console.WriteLine(t2 - t1);
}

C ++-配列:

static void TestArray()
{
    cout << "Normal array test:" << endl;
    const int rows = 5000;
    const int columns = 9000;
    clock_t start, finish;

    start = clock();
    double** arr = new double*[rows];
    for (int i = 0; i < rows; i++)
        arr[i] = new double[columns];
    finish = clock();

    cout << (finish - start) << endl;

    start = clock();
    for (int i = 0; i < rows; i++)
        for (int j = 0; j < columns; j++)
            arr[i][j] = i * j;
    finish = clock();

    cout << (finish - start) << endl;
}

C#-配列:

private static void TestArray()
{
    const int rows = 5000;
    const int columns = 9000;
    DateTime t1 = System.DateTime.Now;
    double[][] arr = new double[rows][];
    for (int i = 0; i < rows; i++)
        arr[i] = new double[columns];
    DateTime t2 = System.DateTime.Now;

    Console.WriteLine(t2 - t1);

    t1 = System.DateTime.Now;
    for (int i = 0; i < rows; i++)
        for (int j = 0; j < columns; j++)
            arr[i][j] = i * j;
    t2 = System.DateTime.Now;

    Console.WriteLine(t2 - t1);

}

時間:(リリース/デバッグ)

C ++

  • 600/606 msアレイ初期化、
  • 200/270ミリ秒の配列充填、
  • 1秒/ 13秒のベクトルの初期化と塗りつぶし。

(はい、13秒です。デバッグモードのリスト/ベクターには常に問題があります。)

C#:

  • 20/20 msアレイの初期化、
  • 403/440 ms配列充填、
  • 710/742 msは、初期化と入力をリストします。

1
std :: listにインデックスアクセサーを表示したいです。とにかく、リスト、リリースモードでは37秒かかります。デバッグなしのリリース:3秒のリスト、0秒、3秒のベクトル。おそらく問題またはsthの逆参照。サンプル:nopaste.pl/12fb
Wiory

2
より正確な測定にはSystem.DateTime.Now、ではなく、Stopwatchクラスを使用する必要があります。
サム

4
C ++でベクターの塗りつぶし時間がこのように遅くなる理由の1つは、push_backを使用していることです。これは、多くの投稿で、atメソッドまたは演算子[]を使用するよりも遅いことが示されています。これらのメソッドのいずれかを使用するには、サイズ変更または予約メソッドを使用する必要があります。さらに、c ++ベクトルの場合に初期化に時間がかかるのは、c ++ベクトルを初期化するために、コピーまたは代入演算子(この場合はどちらかわからない)を強制しているためです。c ++の配列には、5001ではなく2つの新しい呼び出しを使用するアルゴリズムがあり、より高速に反復できます。
ザカリークラウス2014年

5
あなたは適切な方法でc ++をしなかったと思います。一目見て、非常に多くの問題が見つかりました。たとえば、vector <vector <double >> myList = vector <vector <double >>()
DAG

2
ワオ。リストとサイズ変更可能な配列の比較からどのような結論を導き出すことができるかはわかりませんが、このようなベクトルを使用する場合は、reserve()、私の友達、reserve()について学ぶ必要があります。
U007D 2016

3

まあ、それは異なります。バイトコードはマシンコードに変換されている場合は(だけではなくJIT)(I平均あなたがプログラムを実行している場合)、プログラムが多くの割り当て/割り当て解除を使用している場合、それは速いので、可能性がGCのアルゴリズムは一つだけのパスを必要とする(理論上)メモリ全体を1回通過しますが、通常のmalloc / realloc / free C / C ++呼び出しは、すべての呼び出しでオーバーヘッドを引き起こします(呼び出しオーバーヘッド、データ構造オーバーヘッド、キャッシュミス;))。

したがって、理論的には可能です(他のGC言語についても)。

ほとんどのプログラマーはとにかくそれを使用しないので、ほとんどのアプリケーションでC#でメタプログラミングを使用できないという極端な欠点は本当にわかりません。

もう1つの大きな利点は、SQLがLINQの「拡張」のように、データベースへの呼び出しを最適化する機会をコンパイラーに提供することです(つまり、コンパイラーは、呼び出された関数がインライン化されている1つの「blob」バイナリーにLINQ全体をコンパイルできます。あなたの使用のために最適化されていますが、私はここで推測しています)。


1
適切なC ++開発者は、あなたが説明する問題に遭遇しません。プログラムでクラスを平手打ちしてC ++と呼ぶことにした悪いCプログラマーだけがこれらの問題を抱えています。
2018年

1
神々の愛のために、これは8歳です、OMFGz
Quonux

より良い最新の答えを自由に与えてください
Quonux 2018年

2

C#で書かれたアプリケーションが高速で実行されているだけでなく、C ++で作成されたアプリが高速で実行されていると思います(C ++はちょうど古い...そしてUNIXも...)
-問題は、実際には-それは何ですか、ユーザー開発者は不満を言っています... C#でコードを非常にシンプルで高速に書くこと(エラーの可能性も増えることを忘れないでください。C++の場合、開発者はメモリリークについて不平を言います)-クラッシュ、DLL間の呼び出し、および「DLL hell」の問題-新しいライブラリによるサポートライブラリと置換ライブラリの問題... プログラミング言語のスキルが高ければ高いほど、ソフトウェアの品質(および速度)が高くなります。
まあ、私見、C#の場合、私たちは非常に快適なUI、ライブラリーの非常に素晴らしい階層、そしてCLIのインターフェースシステム全体を持っています。C ++の場合、テンプレート、ATL、COM、MFC、およびOpenGL、DirectXなどの既に記述された実行中のコード全体のシバンがあります...開発者は、C#の場合、GC呼び出しが確実に発生しないと不平を言っています(プログラムが高速に実行され、 1秒で-強打!


2

私はこのように言います:より高速なコードを書くプログラマーは、現在のマシンを高速化するものについてより多くの情報を提供されるプログラマーであり、偶然にも、彼らはまた、正確な低レベルかつ確定性を可能にする適切なツールを使用するものです最適化手法。これらの理由から、これらの人々はC#ではなくC / C ++を使用する人々です。私はこれを事実として述べるまで行きます。


Notchは、操作するデータ量を考慮して、Minecraftをかなり高速にコーディングしました。また、C ++では事実上不可能であった比較的短い時間で、ほとんどが単独でコード化しました。ただし、最適化手法には同意します。コードを2倍の速度で実行するために10倍の開発時間を費やす必要がある場合は、それだけの価値があります。
ビルK

2

私が間違っていなければ、C#テンプレートは実行時に決定されます。これは、C ++のコンパイル時テンプレートよりも低速でなければなりません。

そして、他の多くの人が言及している他のすべてのコンパイル時最適化を取り入れると、安全性の欠如だけでなく、実際にはより高速になります...

生の速度と最小のメモリ消費量の点で、C ++が明らかな選択だと思います。しかし、これはコードの開発により多くの時間を費やし、メモリのリークやNULLポインタ例外の発生がないことを意味します。

評決:

  • C#:開発が速く、実行が遅い

  • C ++:遅い開発、速い実行。


1

これは、実際にコードで達成しようとしていることに依存します。VB.NET、C#、マネージドC ++の間にパフォーマンスの違いがあるというのは都市の伝説にすぎないと聞いています。ただし、少なくとも文字列の比較では、マネージドC ++がC#からズボンを打ち負かし、それがVB.NETからズボンを打ち負かすことがわかりました。

言語間のアルゴリズムの複雑さを徹底的に比較したことはありません。また、各言語のデフォルト設定も使用しています。VB.NETでは、変数の宣言などを要求するために設定を使用しています。マネージドC ++に使用しているコードは次のとおりです(ご覧のとおり、このコードは非常に簡単です)。.NET 4.6.2を使用するVisual Studio 2013の他の言語でも同じように実行しています。

#include "stdafx.h"

using namespace System;
using namespace System::Diagnostics;

bool EqualMe(String^ first, String^ second)
{
    return first->Equals(second);
}
int main(array<String ^> ^args)
{
    Stopwatch^ sw = gcnew Stopwatch();
    sw->Start();
    for (int i = 0; i < 100000; i++)
    {
        EqualMe(L"one", L"two");
    }
    sw->Stop();
    Console::WriteLine(sw->ElapsedTicks);
    return 0;
}

1

C#とC ++の間には、パフォーマンスの面でいくつかの大きな違いがあります。

  • C#はGC /ヒープベースです。メモリアクセスの非局所性として、割り当てとGC自体がオーバーヘッドになります。
  • C ++オプティマイザは、長年にわたって非常に優れたものになっています。JITコンパイラーはコンパイル時間が限られており、グローバルスコープを認識しないため、同じレベルを達成できません

そのほかに、プログラマーの能力も役割を果たします。クラス全体で引数として値によって渡されるクラスが不適切なC ++コードを見たことがあります。実際に何をしているのかわからない場合、C ++では実際にパフォーマンスが低下する可能性があります。


0

>結局のところ、答えはどこかにあるはずですよね。:)

うーん、違う。

いくつかの回答が指摘しているように、質問は回答ではなく質問に応じて招待する方法で詳細に指定されていません。たった1つの方法で:

そして、どのプログラム?どの機械?どのOSですか?どのデータセット?


私は完全に同意します。一般的な質問をすると、なぜ正確な回答(63.5%)を期待するのでしょうか。この種の質問に対する一般的な回答はないと思います。
私をスティーブと呼んで

@callmesteve:私はあなたが何を意味しているのか知っていますが、あなたの最後の文はどのプログラマーにとっても黒板の上の釘のように聞こえるはずです。
Wouter van Nifterick、2010年

1
これは質問に答えるようには見えず、コメントまたは暴言としてさらに読みます。
Tas

-13

これに触発されて、私はほとんどのプログラムで必要な一般的な命令の60%で簡単なテストを行いました。

C#コードは次のとおりです。

for (int i=0; i<1000; i++)
{
    StreamReader str = new StreamReader("file.csv");
    StreamWriter stw = new StreamWriter("examp.csv");
    string strL = "";
    while((strL = str.ReadLine()) != null)
    {
        ArrayList al = new ArrayList();
        string[] strline = strL.Split(',');
        al.AddRange(strline);
        foreach(string str1 in strline)
        {
            stw.Write(str1 + ",");
        }
        stw.Write("\n");
    }
    str.Close();
    stw.Close();
}

文字列配列とarraylistは、これらの命令を含めるために意図的に使用されています。

これがc ++コードです:

for (int i = 0; i<1000; i++)
{
    std::fstream file("file.csv", ios::in);
    if (!file.is_open())
    {
        std::cout << "File not found!\n";
        return 1;
    }

    ofstream myfile;
    myfile.open ("example.txt");
    std::string csvLine;

    while (std::getline(file, csvLine))
    {
        std::istringstream csvStream(csvLine);
        std::vector csvColumn;
        std::string csvElement;

        while( std::getline(csvStream, csvElement, ‘,’) )
        {
            csvColumn.push_back(csvElement);
        }

        for (std::vector::iterator j = csvColumn.begin(); j != csvColumn.end(); ++j)
        {
            myfile << *j << ", ";
        }

        csvColumn.clear();
        csvElement.clear();
        csvLine.clear();
        myfile << "\n";
    }
    myfile.close();
    file.close();
}

私が使用した入力ファイルのサイズは40 KBでした。

そして、これが結果です-

  • C ++コードは9秒で実行されました。
  • C#コード:4秒!!!

ああ、でもこれはLinuxで... C#がMonoで実行されていて...そしてC ++がg ++で。

OK、これは私がWindowsで得たものです– Visual Studio 2003

  • C#コードは9秒で実行されました。
  • C ++コード–恐ろしい370秒!!!

7
ここではさまざまなデータ構造とライブラリコードを使用していますが、「370秒」は何か恐ろしいことを示しています。たぶん、デバッガで実行していないのですか。使用しているCSVライブラリのパフォーマンスは、使用している言語のパフォーマンスよりも興味深いと思います。そのような状況でのベクターの使用と、どのような最適化を使用したのか疑問に思います。さらに、少なくともいくつかの一般的な実装では、iostream(特に、「myfile << * j <<」、「;」)が他のファイル書き込み方法よりもはるかに遅いことが広く知られています。
アラファンギオン、

6
最後に、C ++バージョンでさらに作業を行います。(なぜ、csvColumn、csvElement、csvLinesをクリアするのですか?)
Arafangion

2
whileループの反復ごとに、std :: istreamおよびstd :: vectorおよびstd :: stringが破棄および再構築されます。while本体は反復のたびにスコープから外れ、whileスコープ内のすべての変数はすべての反復で破壊および構築されます。
doug65536 2013年

1
あるファイルから別のファイルにコピーしようとしているc ++コードを読んでいる様子から。ファイルストリーム、文字列、ベクター、文字列ストリーム間の複雑な相互作用を使用する代わりに、入力ファイルストリームを出力ファイルストリームにコピーするだけで済みます。これは多くの時間とメモリを節約するでしょう。
Zachary Kraus 2014年

2
速度テストを行うには、メモリ内の物事をディスクIOに到達させないでください。最新のSSDとパフォーマンスアプリ専用のSSDでテストしてください。キーボードに触れなくても、コンピューターは常にディスクに書き込むため。
user3800527
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.