それとも今は逆?
私が聞いたところによると、C# が C++ よりも高速であることが証明されている領域がいくつかありますが、自分でテストする勇気がありませんでした。
これらの違いを詳細に説明したり、これに関する情報の適切な場所を教えてくれる人がいると思いました.
それとも今は逆?
私が聞いたところによると、C# が C++ よりも高速であることが証明されている領域がいくつかありますが、自分でテストする勇気がありませんでした。
これらの違いを詳細に説明したり、これに関する情報の適切な場所を教えてくれる人がいると思いました.
JIT を持つ C# や Java などのバイトコード ベースの言語が、C++ コードほど高速ではないという厳密な理由はありません。しかし、C++ コードは長い間非常に高速であり、現在でも多くの場合は高速です。これは主に、より高度な JIT 最適化の実装が複雑であるためであり、本当に優れた最適化はたった今登場したばかりです。
したがって、多くの場合、C++ の方が高速です。しかし、これは答えのほんの一部です。C++ が実際に高速であるケースは、高度に最適化されたプログラムであり、熟練したプログラマーがコード全体を徹底的に最適化しています。これは非常に時間がかかる (したがって費用がかかる) だけでなく、過剰な最適化によるエラーが発生することもよくあります。
一方、インタープリター型言語のコードは、新しいバージョンのランタイム (.NET CLR または Java VM) では、何もしなくても高速になります。また、ポインターを使用する言語では不可能な、JIT コンパイラーが実行できる便利な最適化が多数あります。また、ガベージ コレクションは一般的に、手動のメモリ管理と同じかそれ以上に高速であるべきだと主張する人もいますが、多くの場合はそうです。通常、これらすべてを C++ または C で実装および実現できますが、はるかに複雑になり、エラーが発生しやすくなります。
Donald Knuth が言ったように、「時期尚早の最適化は諸悪の根源です」。アプリケーションの大部分が非常にパフォーマンスが重要な算術演算で構成され、それがボトルネックになることが確実にわかっている場合、C++ で確実に高速になり、C++ が他のアプリケーションと競合しないことが確実な場合要件については、C++ を使用してください。それ以外の場合は、まず自分に最適な言語でアプリケーションを正しく実装することに専念し、実行速度が遅すぎる場合はパフォーマンスのボトルネックを見つけてから、コードを最適化する方法を考えてください。最悪の場合、外部関数インターフェイスを介して C コードを呼び出す必要があるかもしれないので、重要な部分を下位レベルの言語で記述することができます。
正しいプログラムを最適化するのは比較的簡単ですが、最適化されたプログラムを修正するのははるかに難しいことに注意してください。
速度の利点の実際のパーセンテージを示すことは不可能です。それは主にコードに依存します。多くの場合、プログラミング言語の実装はボトルネックにはなりません。http://benchmarksgame.alioth.debian.org/のベンチマークを非常に懐疑的に見てください。これらは主に算術コードをテストするものであり、おそらくあなたのコードとはまったく似ていません。
C# は高速ではないかもしれませんが、YOU/ME は高速になります。それが私がやっていることの最も重要な尺度です。:)
みかん5個分速いです。というか、(正しい)包括的な答えはあり得ません。C++ は静的にコンパイルされた言語です (ただし、プロファイルに基づく最適化もあります)。C# は JIT コンパイラによって支援されて実行されます。非常に多くの違いがあるため、「どれくらい速いか」などの質問には、桁違いに答えても答えられません。
私の経験では (両方の言語で多くの作業を行ってきました)、C++ と比較した C# の主な問題はメモリ消費量が多いことであり、それを制御する良い方法が見つかりませんでした。最終的に .NET ソフトウェアの速度を低下させるのはメモリ消費でした。
もう 1 つの要因は、JIT コンパイラーは実行時に実行されるため、高度な最適化を行うのに十分な時間を確保できないことです。時間がかかりすぎると、エンド ユーザーはそれに気付くでしょう。一方、C++ コンパイラには、コンパイル時に最適化を行うために必要な時間が常にあります。この要因は、メモリ消費量よりもはるかに重要ではありません。
コンパイル時にポリモーフィックな決定を事前に決定できる場合、C++ がまだ優勢である (そして、今後数年間は優勢になる) 特定のシナリオが 1 つ発生します。
一般に、カプセル化と遅延意思決定は、コードをより動的にし、変化する要件に適応しやすくし、フレームワークとして使いやすくするため、良いことです。これが、C# でのオブジェクト指向プログラミングが非常に生産的であり、「一般化」という用語で一般化できる理由です。残念ながら、この特定の種類の一般化には、実行時のコストがかかります。
通常、このコストは重要ではありませんが、仮想メソッド呼び出しとオブジェクト作成のオーバーヘッドが違いを生むアプリケーションがあります (特に、仮想メソッドがメソッド呼び出しのインライン化などの他の最適化を妨げるため)。これは、C++ が大きな利点を持っている場所です。テンプレートを使用して、ランタイムに影響を与えず、必ずしも OOP よりもポリモーフィックではない別の種類の一般化を実現できるからです。実際、OOP を構成するすべてのメカニズムは、テンプレート手法とコンパイル時の解決のみを使用してモデル化できます。
そのような場合 (そして確かに、それらは多くの場合、特別な問題領域に制限されています)、C++ は C# や同等の言語よりも優れています。
C ++(またはC)を使用すると、データ構造をきめ細かく制御できます。ビットをいじりたい場合は、そのオプションがあります。Java / .NETライブラリの内部データ構造を使用する大規模なマネージドJavaまたは.NETアプリ(OWB、Visual Studio 2005)は、手荷物を運びます。キューブまたはETL設計に400MBを超えるRAMとBIDSを使用するOWBデザイナーセッションも数百MBに達するのを見てきました。
予測可能なワークロード(プロセスを何度も繰り返すほとんどのベンチマークなど)では、JITを使用すると、実用的な違いがないほど十分に最適化されたコードを取得できます。
大規模なアプリケーションでのIMOの違いは、コード自体が使用しているデータ構造ほどJITではありません。アプリケーションがメモリを大量に消費する場合、キャッシュの使用効率が低下します。最近のCPUでのキャッシュミスは非常に高価です。CまたはC++が実際に勝つのは、データ構造の使用を最適化してCPUキャッシュとうまく連携できる場所です。
グラフィックスの場合、標準のC#グラフィックスクラスは、C /C++経由でアクセスされるGDIよりもはるかに低速です。これは言語自体とは関係がなく、.NETプラットフォーム全体と関係があることは知っていますが、グラフィックスはGDIの代替として開発者に提供されるものであり、そのパフォーマンスは非常に悪いので、グラフィックスをあえてすることすらできません。それと。
グラフィックライブラリの速度を確認するために使用する簡単なベンチマークがあります。これは、ウィンドウにランダムな線を描画するだけです。C ++ / GDIはまだ10000行でスッキリしていますが、C#/Graphicsはリアルタイムで1000を実行するのが困難です。
Java# がリアルタイム システムに使用できない主な理由は、ガベージ コレクションです。
GC はいつ行われますか?
どのくらい時間がかかりますか?
これは非決定的です。
C# のパフォーマンスが C++ に匹敵するかどうかを判断する必要があり、そのためのテスト プログラムをいくつか作成しました (両方の言語で Visual Studio 2005 を使用)。ガベージ コレクションを使用せず、(フレームワークではなく) 言語のみを考慮すると、C# のパフォーマンスは基本的に C++ と同じであることが判明しました。メモリ割り当ては、C++ よりも C# の方がはるかに高速であり、データ サイズがキャッシュ ラインの境界を超えて増加した場合、C# は確定性においてわずかに優れています。ただし、最終的にはこれらすべての費用を支払う必要があり、ガベージ コレクションによる C# の非決定論的なパフォーマンス ヒットという形で莫大なコストがかかります。
ご質問の内容とは異なることは承知していますが、C# は C++ よりも高速に記述できることが多く、これは商用環境では大きな利点です。
いつものように、それはアプリケーションに依存します。C# の方がおそらく無視できるほど遅い場合もあれば、C++ の方が 5 倍または 10 倍高速な場合もあります。特に操作が簡単に SIMD 化できる場合です。
>聞いた話では・・・
あなたの難しさは、あなたが聞いたことが信憑性があるかどうかを判断することであると思われます.このサイトの回答を評価しようとすると、その困難が繰り返されます.
ここで人々が言っていることが、最初に聞いたものよりも信頼できるかどうかをどのように判断しますか?
1 つの方法は、証拠を求めることです。
誰かが「C# が C++ よりも高速であることが証明されている領域がある」と主張する場合、その理由を尋ね、測定値を見せてもらい、プログラムを見せてもらいます。単に間違いを犯しただけの場合もあります。彼らが真実であることを示すことができる何かを共有するのではなく、単に意見を表明していることに気付くことがあります.
多くの場合、人々の主張には情報と意見が混同されており、どちらがどちらであるかを整理する必要があります。たとえば、このフォーラムの返信から:
「 http://shootout.alioth.debian.org/のベンチマークを 非常に懐疑的に見てください。これらは主に算術コードをテストするものであり、おそらくあなたのコードとはまったく似ていないからです。」
「これらの主にテスト算術コード」が何を意味するのかを本当に理解しているかどうかを自問してから、著者が自分の主張が真実であることを実際に示したかどうかを自問してください。
「個々のプログラムがどれだけ最適化されているかに大きく依存するため、これはかなり役に立たないテストです。そのうちのいくつかを 4 ~ 6 倍以上高速化することができました。最適化されていないプログラム間の比較は、馬鹿な。"
著者が「それらの一部を 4 ~ 6 倍以上高速化」したことを実際に証明したかどうか自問してみてください。これは簡単に主張できます。
「驚異的並列」の問題の場合、C++でIntelTBBとOpenMPを使用すると、C#とTPLで行われる同様の(純粋数学)問題と比較して、パフォーマンスが約10倍向上することがわかりました。SIMDはC#が競合できない領域の1つですが、TPLにはかなりのオーバーヘッドがあるという印象もありました。
とは言うものの、C ++は、マルチスレッド化して結果をすばやく取得できることがわかっている、パフォーマンスが重要なタスクにのみ使用します。それ以外の場合は、C#(場合によってはF#)で問題ありません。
本当に決定的な答えのない非常に漠然とした質問です。
例えば; 私は、C# よりも C++ で作成された 3D ゲームをプレイしたいと思っています。パフォーマンスは確かにはるかに優れているからです。(そして、XNAなどは知っていますが、本物にはほど遠いです)。
一方、前述のように。必要なことをすばやく実行できる言語で開発し、必要に応じて最適化する必要があります。
理論的には、長時間実行されるサーバー タイプのアプリケーションの場合、JIT でコンパイルされた言語は、ネイティブでコンパイルされた対応する言語よりもはるかに高速になる可能性があります。JIT コンパイル言語は通常、最初にかなり低レベルの中間言語にコンパイルされるため、コンパイル時に多くの高レベルの最適化を行うことができます。大きな利点は、JIT がアプリケーションの使用状況に関するデータを取得するにつれて、コードのセクションをオンザフライで再コンパイルし続けることができることです。分岐予測ができるだけ頻繁に成功するように、最も一般的なコード パスを配置できます。一緒に呼び出されることが多い個別のコード ブロックを再配置して、両方をキャッシュに保持できます。内部ループの最適化により多くの労力を費やすことができます。
これが .NET や JRE によって行われているとは思えませんが、私が大学時代に研究されていたので、この種のことが近いうちに現実世界に浸透する可能性があると考えるのは不合理ではありません。 .
.NET 言語は C++ コードと同じかそれ以上に高速ですが、.NET ランタイムはGCのために一時停止する必要があるため、一時停止について非常に巧妙であっても、C++ コードのスループットはより一定です。
したがって、一時停止することなく一貫して高速に実行する必要があるコードがある場合、.NET は、ランタイム GC に十分注意していても、ある時点でレイテンシーを導入します。
集中的なメモリ アクセスを必要とするアプリケーション。画像操作は通常、マネージド (C#) よりもアンマネージド (C++) 環境で記述した方が適切です。ポインター演算を使用する最適化された内部ループは、C++ で制御するのがはるかに簡単です。C# では、同じパフォーマンスに近づけるために、安全でないコードに頼る必要がある場合があります。
私はvector
C++ と C# の同等物List
と単純な 2 次元配列でテストしました。
Visual C#/C++ 2010 Express エディションを使用しています。どちらのプロジェクトも単純なコンソール アプリケーションです。標準 (カスタム設定なし) のリリースおよびデバッグ モードでテストしました。C# のリストは私の PC で高速に実行され、配列の初期化も 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++
(はい、13 秒です。デバッグ モードのリスト/ベクターには常に問題があります。)
C#:
まあ、それは依存します。バイトコードが(JITだけでなく)マシンコードに変換されている場合(つまり、プログラムを実行する場合)、プログラムが多くの割り当て/割り当て解除を使用する場合、GCアルゴリズムは(理論的には)1回のパスしか必要としないため、より高速になる可能性がありますただし、通常の malloc/realloc/free C/C++ 呼び出しでは、すべての呼び出しでオーバーヘッドが発生します (呼び出しオーバーヘッド、データ構造オーバーヘッド、キャッシュ ミス;))。
したがって、理論的には可能です(他のGC言語でも可能です)。
ほとんどのアプリケーションで C#を使用したメタプログラミングを使用できないことの極端な欠点は、実際にはわかりません。
もう 1 つの大きな利点は、LINQの"拡張機能" と同様に、SQL がコンパイラにデータベースへの呼び出しを最適化する機会を提供することです (つまり、コンパイラは LINQ 全体を 1 つの "blob" バイナリにコンパイルし、呼び出された関数がインライン化またはあなたの使用のために最適化されていますが、私はここで推測しています)。
C# で書かれたアプリケーションが高速に動作するだけでなく、C++ で記述されたアプリケーションが高速に動作することもあると思います (C++ は少し古いですが、UNIX も使用します...)。そして開発者は不満を言っています...
まあ、私見ですが、C#の場合、非常に快適なUI、ライブラリの非常に優れた階層、およびCLIのインターフェイスシステム全体があります。C++ の場合、テンプレート、ATL、COM、MFC、および OpenGL、DirectX などのように既に作成され実行されているコードのシバン全体があります。 1 秒で - バン! 動かなくなった)。
C# でコードを書くことは非常に簡単かつ迅速です (これもエラーの可能性を高めることを忘れないでください。C++ の場合、開発者はメモリ リークを訴えます。つまり、クラッシュ、DLL 間の呼び出し、および「DLL 地獄」の問題です。新しいライブラリによるサポートと置換ライブラリ...
プログラミング言語のスキルが高いほど、ソフトウェアの品質 (および速度) が向上すると思います。
私はこのように言います: より速いコードを書くプログラマーは、現在のマシンが速くなる理由についてより多くの情報を持っている人であり、偶然にも、彼らは正確な低レベルで決定論的なことを可能にする適切なツールを使用する人でもあります.最適化技術。これらの理由から、これらの人々は C# ではなく C/C++ を使用する人です。私はこれを事実として述べるところまで行きます。
この 2020 年 4 月の読み物を見つけました: https://www.quora.com/Why-is-C-so-slow-compared-to-Pythonは、15 年以上のソフトウェア開発経験を持つ現実世界のプログラマーによるものです。
C# は通常、C++ のようなマシン コードではなく共通中間言語 (CIL)にコンパイルされるため、低速であると述べています。次に、CIL はマシン コードを出力する共通言語ランタイム (CLR)に渡されます。ただし、C# を実行し続けると、マシン コードの出力が取得されてキャッシュされるため、次回の実行のためにマシン コードが保存されます。全体として、C# は複数回実行した後にマシン コードであるため、複数回実行すると高速になる可能性があります。
優れた C++ プログラマーは、最終的には最適化される、時間がかかる可能性のある最適化を行うことができるというコメントもあります。
私が C++ と C# でコードをインストルメント化していた領域の 1 つは、SQL Server へのデータベース接続を作成し、結果セットを返すことでした。C++ (ODBC 上のシン レイヤー) と C# (ADO.NET SqlClient) を比較したところ、C++ は C# コードよりも約 50% 高速であることがわかりました。ADO.NET は、データベースを処理するための低レベルのインターフェイスであると想定されています。おそらく大きな違いは、生の速度ではなくメモリ消費量にあります。
C++ コードを高速化するもう 1 つの理由は、C# ではできない方法でコンパイラ オプションを調整して最適化できることです。
これに触発されて、私はほとんどのプログラムで必要な一般的な命令の 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();
}
文字列配列と配列リストは、これらの命令を含めるために意図的に使用されます。
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 でした。
そして、これが結果です-
ああ、でもこれは Linux で... Monoで実行されている C# で... そして C++ で g++ を使用していました。
OK、これは私が Windows – Visual Studio 2003で得たものです: