2013-03-25 30 views
16

Tôi đã đo thời gian thực hiện cho hai cách tính lũy thừa của 2:C#: Tại sao cuộc gọi hàm nhanh hơn so với nội tuyến thủ công?

1) Inline

result = b * b; 

2) Với chức năng cuộc gọi đơn giản

result = Power(b); 

Khi chạy trong chế độ Debug, mọi thứ đều như mong đợi: Gọi một hàm đắt hơn đáng kể so với thực hiện phép tính theo dòng (385 ms trong dòng so với 570 ms gọi hàm).

Trong chế độ phát hành, tôi mong đợi trình biên dịch tăng tốc thời gian thực hiện của cuộc gọi hàm đáng kể bởi vì trình biên dịch sẽ nội dòng hàm rất nhỏ Power(). Nhưng tôi không mong đợi các chức năng gọi là nhanh hơn so với tính toán inlined thủ công.

Đáng ngạc nhiên nhất là trường hợp này: Trong bản phát hành, lần chạy đầu tiên cần 109 ms và lần chạy thứ hai với lệnh gọi tới số Power() chỉ cần 62 ms.

Cách gọi hàm nhanh hơn so với hướng dẫn thủ công?

Dưới đây là chương trình cho sinh sản của bạn:

class Program 
{ 
    static void Main(string[] args) 
    { 
     Console.WriteLine("Starting Test"); 

     // 1. Calculating inline without function call 
     Stopwatch sw = Stopwatch.StartNew(); 

     for (double d = 0; d < 100000000; d++) 
     { 
      double res = d * d; 
     } 

     sw.Stop(); 
     Console.WriteLine("Checked: " + sw.ElapsedMilliseconds); 

     // 2. Calulating power with function call 
     Stopwatch sw2 = Stopwatch.StartNew(); 

     for (int d = 0; d < 100000000; d++) 
     { 
      double res = Power(d); 
     } 

     sw2.Stop(); 
     Console.WriteLine("Function: " + sw2.ElapsedMilliseconds); 

     Console.ReadKey(); 
    } 

    static double Power(double d) 
    { 
     return d * d; 
    } 
} 
+0

Bạn có bắt đầu chương trình trong trình gỡ lỗi (F5) không? Trong trường hợp đó tối ưu hóa đã bị đàn áp. – usr

+1

Bạn có chạy .exe được tạo hoặc trong VS ở chế độ phát hành không? Ngoài ra, bạn đã thử gọi chúng theo các đơn đặt hàng khác nhau chưa? Tôi đã tìm thấy điều này làm cho một sự khác biệt tinh tế – DGibbs

+0

Vâng, tại sao sử dụng một int ** như là một đôi ** nhanh hơn so với chỉ sử dụng một đôi? – Vercas

Trả lời

50

thử nghiệm của bạn là sai. Trong phần thứ hai, bạn sử dụng một số int d thay vì một đôi. Có lẽ nó giải thích sự khác biệt thời gian.

+0

Cũng phát hiện !!! – DGibbs

+0

Thời gian chạy của hàm số luôn chậm hơn dòng nội tuyến trên máy tính của tôi (bất kể int hay double). – iamsleepy

+0

Hoàn toàn đúng. Tôi bị mù. Bạn đã giải quyết nó! Cảm ơn! – Knasterbax

22

Khi Xavier phát hiện chính xác, bạn đang sử dụng vòng lặp đôi trong một và int trong vòng kia. Thay đổi cả hai thành cùng một loại sẽ làm cho các kết quả giống nhau - tôi đã thử nghiệm nó.

Hơn nữa: Điều bạn thực sự đo lường ở đây là thời lượng bổ sung và so sánh. Bạn đang không đo thời lượng của bình phương d, bởi vì nó đơn giản là không xảy ra: Trong bản phát hành bản phát hành, trình tối ưu hóa sẽ loại bỏ hoàn toàn phần thân của vòng lặp, vì kết quả không được sử dụng. Bạn có thể xác nhận điều này bằng cách bình luận ra phần thân của vòng lặp. Thời gian sẽ giống nhau.

+0

Cũng hoàn toàn đúng. Đó là sai lầm của tôi. Tôi đã giám sát các int – Knasterbax

3

Daniel Hilgarth là đúng, tính toán không xảy ra ở tất cả là kết quả của không được sử dụng (có lẽ không phải là trường hợp trong chế độ gỡ lỗi). Hãy thử ví dụ sau và bạn sẽ nhận được kết quả chính xác:

static void Main(string[] args) 
    { 
     Console.WriteLine("Starting Test"); 
     var list = new List<int>(); 
     // 1. Calculating inline without function call 
     Stopwatch sw = Stopwatch.StartNew(); 

     for (int d = 0; d < 100000000; d++) 
     { 
      int res = d * d; 
      list.Add(res); 
     } 

     sw.Stop(); 
     Console.WriteLine("Checked: " + sw.ElapsedMilliseconds); 
     // 2. Calulating power with function call 

     list = new List<int>(); 
     Stopwatch sw2 = Stopwatch.StartNew(); 

     for (int d = 0; d < 100000000; d++) 
     { 
      int res = Power(d); 
      list.Add(res); 
     } 

     sw2.Stop(); 
     Console.WriteLine("Function: " + sw2.ElapsedMilliseconds); 

     Console.ReadKey(); 
    } 
+2

Sẽ không mã này ném một 'OverflowException' kể từ' res' cuối cùng sẽ được cách trên 'Int32.MaxValue' trong những vòng? – Drewman