Tôi sẽ bắt đầu bằng cách không đồng ý với một phần câu trả lời được chấp nhận (và được nâng cao) cho câu hỏi này bằng cách nêu:
Thực tế có rất nhiều lý do tại sao mã JITted sẽ chạy chậm hơn chương trình C ++ (hoặc ngôn ngữ khác không có thời gian chạy) được tối ưu hóa đúng cách bao gồm:
tính toán các chu kỳ chi cho mã JITting trong thời gian chạy theo định nghĩa không có sẵn để sử dụng trong thực thi chương trình.
mọi đường dẫn nóng trong JITter sẽ cạnh tranh với mã của bạn để được hướng dẫn và lưu trữ dữ liệu trong CPU. Chúng tôi biết rằng bộ đệm chiếm ưu thế khi nói đến hiệu suất và các ngôn ngữ bản địa như C ++ không có kiểu tranh chấp này, theo định nghĩa.
ngân sách thời gian một thời gian chạy tối ưu được thiết nhiều hơn hạn chế hơn so với các phần mềm tối ưu thời gian biên dịch của (như commenter khác chỉ ra)
Bottom line: Cuối cùng, bạn sẽ gần như chắc chắn có thể tạo ra một thực hiện nhanh hơn trong C ++ hơn bạn có thể trong C # .
Bây giờ, như đã nói, thực sự nhanh hơn bao nhiêu không thể định lượng được, vì có quá nhiều biến số: nhiệm vụ, miền vấn đề, phần cứng, chất lượng triển khai và nhiều yếu tố khác. Bạn sẽ chạy thử nghiệm trên kịch bản của mình để xác định sự khác biệt về hiệu suất và sau đó quyết định xem nó có xứng đáng với nỗ lực và độ phức tạp bổ sung hay không.
Đây là một chủ đề rất dài và phức tạp, nhưng tôi cảm thấy đáng để đề cập vì sự hoàn hảo của trình tối ưu hóa thời gian chạy của C # là tuyệt vời và có thể thực hiện một số tối ưu hóa động nhất định trong thời gian chạy mà C ++ không có sẵn trong thời gian biên dịch của nó ( tối ưu hóa tĩnh). Ngay cả với điều này, lợi thế vẫn nằm sâu trong tòa án của ứng dụng gốc, nhưng trình tối ưu hóa động là lý do cho vòng loại " gần như chắc chắn" được đưa ra ở trên.
-
Về hiệu suất tương đối, tôi cũng bị làm phiền bởi các số liệu và thảo luận mà tôi đã thấy trong một số câu trả lời khác, vì vậy tôi nghĩ rằng tôi đồng thời đồng ý, cung cấp một số hỗ trợ cho các tuyên bố tôi đã đưa ra ở trên.
Một phần lớn của vấn đề với các điểm chuẩn đó là bạn không thể viết mã C ++ như thể bạn đang viết C # và mong muốn nhận được kết quả đại diện (ví dụ: thực hiện hàng ngàn phân bổ bộ nhớ trong C ++ sẽ mang lại cho bạn những con số khủng khiếp.)
Thay vào đó, tôi đã viết mã C ++ thành ngữ hơn một chút và so sánh với mã C # @Wiory cung cấp. Hai thay đổi chính mà tôi đã thực hiện đối với mã C ++ là:
1) vectơ đã sử dụng :: reserved ()
2) làm phẳng mảng 2d thành 1d để đạt được vị trí bộ đệm tốt hơn (khối liền kề)
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);
}
Thời gian chạy (Phát hành): Ban đầu: 124ms, Điền: 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);
}
Thời gian chạy (Phát hành): Ban đầu: 398 Điên (vâng, đó là micro giây), Điền: 152ms
Tổng thời gian chạy: C #: 289ms, C ++ 152ms (nhanh hơn khoảng 90%)
Quan sát
Thay đổi triển khai C # thành cùng triển khai mảng 1d mang lại Ban đầu: 40ms, Điền: 171ms, Tổng cộng: 211ms ( C ++ vẫn nhanh hơn gần 40% ).
Thiết kế và viết mã "nhanh" trong C ++ khó hơn nhiều so với viết mã "thông thường" bằng một trong hai ngôn ngữ.
Thật đáng kinh ngạc khi có được hiệu suất kém trong C ++; chúng tôi đã thấy rằng với hiệu suất vectơ không được giám sát. Và có rất nhiều cạm bẫy như thế này.
Hiệu suất của C # khá tuyệt vời khi bạn xem xét tất cả những gì đang diễn ra trong thời gian chạy. Và hiệu suất đó là tương đối dễ dàng để truy cập.
Thêm dữ liệu giai thoại so sánh hiệu suất của C ++ và C #: https://benchmarkgame.alioth.debian.org/u64q/compare.php?lang=gpp&lang2=csharpcore
Điểm mấu chốt là C ++ cho phép bạn kiểm soát hiệu năng nhiều hơn. Bạn có muốn sử dụng một con trỏ? Một tài liệu tham khảo? Bộ nhớ ngăn xếp? Đống? Đa hình động hoặc loại bỏ chi phí thời gian chạy của một vtable với đa hình tĩnh (thông qua các mẫu / CRTP)? Trong C ++, bạn phải ... er, tự mình thực hiện tất cả các lựa chọn này (và hơn thế nữa), để giải pháp của bạn giải quyết tốt nhất vấn đề bạn đang giải quyết.
Hãy tự hỏi mình nếu bạn thực sự muốn hoặc cần sự kiểm soát đó, bởi vì ngay cả đối với ví dụ tầm thường ở trên, bạn có thể thấy rằng mặc dù có một sự cải thiện đáng kể về hiệu suất, nó đòi hỏi một sự đầu tư sâu hơn để truy cập.