Bu soruya kabul edilen (ve iyi değerlendirilmiş) cevabın bir kısmına şunu söyleyerek katılmıyorum:
JITted kodunun uygun şekilde optimize edilmiş bir C ++ (veya çalışma zamanı ek yükü olmayan başka bir dil) programından daha yavaş çalışmasının birçok nedeni vardır :
çalışma zamanında JITting koduna harcanan hesaplama döngüleri, tanım gereği, program yürütülmesinde kullanılamaz.
JITter'daki herhangi bir etkin yol, CPU'daki talimat ve veri önbelleği için kodunuzla rekabet edecektir. Performans söz konusu olduğunda önbelleğin baskın olduğunu biliyoruz ve C ++ gibi anadillerde tanım gereği bu tür bir çekişme yok.
bir çalışma zamanı optimize edicisinin zaman bütçesi, derleme zamanı optimize edicisinin bütçesinden çok daha kısıtlıdır (başka bir yorumcunun belirttiği gibi)
Sonuç: Sonuçta, sen olacak neredeyse kesinlikle C # yapabileceğinden daha C ++ daha hızlı uygulanmasını oluşturabileceksiniz .
Şimdi, bununla birlikte, ne kadar hızlı , çok fazla değişken olduğu için gerçekten ölçülemez: görev, sorun alanı, donanım, uygulamaların kalitesi ve diğer birçok faktör. Performans farkını belirlemek için senaryonuzda testler yaparsınız ve daha sonra ek çaba ve karmaşıklığa değip değmeyeceğine karar verirsiniz.
Bu çok uzun ve karmaşık bir konudur, ancak C # 'ın çalışma zamanı optimize edicisinin mükemmel olduğu ve derleme zamanı ile C ++ tarafından kullanılamayan belirli dinamik optimizasyonları gerçekleştirebildiği tamlık uğruna bahsetmeye değer hissediyorum. statik) optimize edici. Bununla bile, avantaj hala tipik olarak yerel uygulamanın mahkemesinde derindir, ancak dinamik optimize edici, yukarıda verilen " neredeyse kesinlikle" niteleyicisinin nedenidir .
-
Göreceli performans açısından, diğer bazı cevaplarda gördüğüm rakamlar ve tartışmalardan da rahatsız oldum, bu yüzden yukarıda verdiğim ifadelere biraz destek vereceğimi düşündüm.
Bu ölçütlerle ilgili sorunun büyük bir kısmı, C # yazıyormuşsunuz gibi C ++ kodu yazamamanız ve temsili sonuçlar almayı beklemenizdir (örn. C ++ 'da binlerce bellek ayırma işlemi yapmak size korkunç sayılar verecektir.)
Bunun yerine, biraz daha deyimsel C ++ kodu yazdım ve sağlanan C # kodu ile karşılaştırıldığında @Wiory. C ++ kodunda yaptığım iki büyük değişiklik:
1) kullanılan vektör :: rezerv ()
2) daha iyi önbellek konumu elde etmek için 2d dizisini 1d'ye düzleştirdi (bitişik blok)
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);
}
Çalışma süresi (Serbest Bırakma): Başlatma: 124ms, Dolgu: 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);
}
Çalışma süresi (Serbest Bırakma): Başlatma: 398µs (evet, bu mikrosaniye), Dolgu: 152ms
Toplam Çalışma süresi: C #: 289ms, C ++ 152ms (kabaca% 90 daha hızlı)
Gözlemler
C # uygulamasının aynı 1d dizi uygulamasına değiştirilmesi Init: 40ms, Fill: 171ms, Toplam: 211ms ( C ++ hala neredeyse% 40 daha hızlıydı ) verdi.
C ++ 'da "hızlı" kod tasarlamak ve yazmak her iki dilde de "normal" kod yazmaktan daha zordur.
C ++ 'da kötü performans elde etmek şaşırtıcı derecede kolaydır; bunu çekilmemiş vektör performansı ile gördük. Ve bunun gibi birçok tuzak var.
C # 'ın performansı, çalışma zamanında olup bittiğini düşündüğünüzde oldukça şaşırtıcı. Ve bu performansa erişmek nispeten daha kolaydır.
C ++ ve C # performansını karşılaştıran daha fazla fıkra verileri: https://benchmarksgame.alioth.debian.org/u64q/compare.php?lang=gpp&lang2=csharpcore
Sonuç olarak, C ++ size performans üzerinde çok daha fazla kontrol sağlıyor. Bir işaretçi kullanmak istiyor musunuz? Referans? Yığın bellek? Yığın? Dinamik polimorfizm veya statik polimorfizm (şablonlar / CRTP aracılığıyla) ile bir vtable çalışma zamanı yükünü ortadan kaldırmak? C ++ 'da ... er, almak zorunda , ideal böylece çözüm iyi adresleri sorun sen tackling olduğunu, (ve daha fazla) kendinizi tüm bu seçimler yapmak.
Kendinize bu kontrolü gerçekten isteyip istemediğinizi sorun, çünkü yukarıdaki önemsiz örnek için bile, performansta önemli bir gelişme olsa da, erişmek için daha derin bir yatırım gerektirdiğini görebilirsiniz.