2012-01-15 36 views
15

Ví dụ, tôi biết nó được định nghĩa cho gcc và được sử dụng trong hạt nhân Linux như:Có thể sử dụng gợi ý nhánh trong C# không?

#define likely(x)  __builtin_expect((x),1) 
#define unlikely(x)  __builtin_expect((x),0) 

Nếu không có gì như thế này là có thể trong C#, là sự thay thế tốt nhất để tự sắp xếp lại nếu-tuyên bố, đưa nhất trường hợp có khả năng đầu tiên? Có cách nào khác để tối ưu hóa dựa trên loại kiến ​​thức bên ngoài này không?

Trên ghi chú liên quan, CLR biết cách xác định các điều khoản bảo vệ và giả định rằng nhánh thay thế sẽ được thực hiện, làm cho tối ưu hóa này không phù hợp để sử dụng trong các cảnh bảo vệ, đúng không?

(Lưu ý rằng tôi nhận ra điều này có thể là một vi-tối ưu hóa; Tôi chỉ quan tâm cho mục đích học tập.)

+4

Bạn sẽ làm như thế nào, khi C# biên dịch thành IL, một mã byte có thể kết thúc sau đó được biên dịch thành bất kỳ CPU gốc nào? – Oded

+0

Câu trả lời là "không, không thể." Lý do cho điều này không thể được chỉ ra bởi Oded. –

+0

Tôi cho rằng tôi đã hy vọng nó có thể được thực hiện trong IL, vì IL được biên dịch xuống mã nguồn gốc, nơi một hướng dẫn cho gợi ý có thể được sử dụng. Hoặc, bất kỳ kỹ thuật tương tự nào khác, ngay cả khi không ở cấp độ bộ vi xử lý sẽ được quan tâm (mặc dù tôi không chắc chắn điều này là có thể). – ceyko

Trả lời

23

Câu trả lời ngắn: Số

dài trả lời: Bạn không thực sự cần trong hầu hết các trường hợp. Bạn có thể đưa ra gợi ý bằng cách thay đổi logic trong câu lệnh của bạn. Điều này dễ dàng hơn khi thực hiện với một công cụ hiệu suất, giống như công cụ được tích hợp vào các phiên bản cao hơn (và đắt tiền hơn) của Visual Studio, vì bạn có thể nắm bắt các bộ đếm chi nhánh bị lỗi. Tôi nhận ra điều này là dành cho mục đích học tập, nhưng thật tuyệt khi biết rằng JITer là rất tối ưu hóa mã của bạn cho bạn. Như một ví dụ (lấy khá nhiều nguyên văn từ CLR via C#)

Mã này:

public static void Main() { 
    Int32[] a = new Int32[5]; 
    for(Int32 index = 0; index < a.Length; index++) { 
     // Do something with a[index] 
    } 
} 

có thể dường như không hiệu quả, vì a.Length là một tài sản và như chúng ta đã biết trong C#, một tài sản thực sự là một tập hợp hai phương thức (get_Lengthset_Length trong trường hợp này). Tuy nhiên, JIT biết rằng đó là một thuộc tính và lưu trữ độ dài trong một biến cục bộ cho bạn, hoặc inline phương thức, để ngăn chặn chi phí.

... một số nhà phát triển đã đánh giá thấp khả năng của trình biên dịch JIT và đã cố gắng để viết “mã thông minh” trong một nỗ lực để giúp trình biên dịch JIT . Tuy nhiên, bất kỳ nỗ lực thông minh nào mà bạn nghĩ ra sẽ gần như chắc chắn tác động tiêu cực đến hiệu suất và làm cho mã của bạn khó đọc hơn, giảm khả năng bảo trì của mã.

Trong số những thứ khác, nó thực sự đi xa hơn và không giới hạn kiểm tra một lần ngoài của vòng lặp thay vì bên trong vòng lặp, mà sẽ làm suy giảm hiệu suất.

Tôi nhận thấy nó không liên quan trực tiếp đến câu hỏi của bạn, nhưng tôi đoán điểm mà tôi đang cố gắng thực hiện là tối ưu hóa vi mô như thế này không thực sự giúp bạn nhiều trong C#, vì JIT thường nó tốt hơn, vì nó được thiết kế chính xác cho việc này. (Thực tế thú vị, trình biên dịch JIT x86 thực hiện tối ưu hóa tích cực hơn so với đối tác x64)

This article giải thích một số tối ưu hóa đã được thêm vào trong .NET 3.5 SP1, trong số đó là các cải tiến cho các nhánh thẳng để cải thiện dự đoán và vùng nhớ đệm. Tất cả điều đó được nói, nếu bạn muốn đọc một cuốn sách tuyệt vời mà đi vào những gì trình biên dịch tạo ra và hiệu suất của CLR, tôi khuyên bạn nên cuốn sách mà tôi trích dẫn từ trên, CLR thông qua C#.

EDIT: Tôi nên đề cập rằng nếu điều này hiện có thể có trong .NET, bạn có thể tìm thông tin trong số EMCA-335 standard hoặc working draft. Không có chuẩn hỗ trợ điều này và việc xem siêu dữ liệu trong một cái gì đó như IlDasm hoặc CFF Explorer không có dấu hiệu của bất kỳ siêu dữ liệu đặc biệt nào có thể gợi ý tại các dự đoán nhánh.

+0

Mặc dù đó là điều đáng thất vọng, nhưng thông tin về JITing vẫn an tâm. Cảm ơn những lời khuyên, tôi chắc chắn sẽ được kiểm tra ra cuốn sách kể từ khi tôi không quá quen thuộc với CLR, nhưng đã rất quan tâm đến những gì thực sự xảy ra "đằng sau hậu trường" gần đây. – ceyko

+0

Trong khi tôi rất thích cuốn sách đó, tôi không thích trích dẫn bạn đưa ra. Nó thực sự chính xác, nhưng tôi không thích những giai điệu về "mã thông minh", đặc biệt là xem xét mọi người chỉ là khinh khi ai đó tự hỏi tại sao một tối ưu hóa nhất định không được thực hiện. Chúng ta có thể tưởng tượng một jitter hoàn hảo kỳ diệu luôn tạo ra mã hiệu quả nhất có thể, và dễ dàng tưởng tượng ra một cái ngớ ngẩn khủng khiếp mà không bao giờ tối ưu bất cứ thứ gì, và chúng ta biết sự thật là ở giữa. Không biết nơi mà điểm đó ở giữa là, mọi người đang cố gắng làm những việc này tại các điểm nóng và xem họ có làm việc hay không. –

+0

@JonHanna - Tôi nghĩ rằng tôi đồng ý với bạn ở mức độ lớn. Tôi không nghĩ rằng nhà phát triển nên bỏ qua những gì JITer đang làm; đó là một chút không may rằng chúng tôi không thực sự biết chính xác những gì đang nhận được tối ưu hóa. Tôi biết nó không hoàn hảo. Tôi cũng biết nó không khủng khiếp. Tuy nhiên, bạn đã nói gọn gàng, chúng tôi chỉ đơn giản là không biết mức độ tối ưu hóa của nó. Cách duy nhất để biết (đối với một phiên bản duy nhất của khung công tác), sẽ xem xét những gì nó đang làm khi nó đang được thực hiện, sử dụng một cái gì đó giống như Windbg. Đó là nói dễ hơn làm, mặc dù. –

Các vấn đề liên quan