2015-03-23 13 views
5

Tôi đang cố gắng so sánh hiệu suất của pow(x,2.0)pow(x,2.0000001) và tôi mặc dù 2.0 sẽ nhanh hơn nhiều, nhưng chúng ở cùng tốc độ. Tôi thậm chí loại bỏ tối ưu hóa JIT bằng cách chạy jar với thông số -Xint.Java Math.pow (x, 2.0) so với hiệu suất Math.pow (x, 2.0000001)

Bất kỳ ý tưởng nào về lý do đó, vui lòng? Cảm ơn rất nhiều!

+1

Việc triển khai miễn phí để chi tiêu chi nhánh có điều kiện để kiểm tra trường hợp đặc biệt hoặc thực hiện tất cả các trường hợp có cùng mã. Tất cả những gì quan trọng là kết quả. Không có đảm bảo về thời gian thực hiện. (Không phải vậy, nếu bạn không cẩn thận, bạn sẽ thấy chúng ngay cả khi chúng ở đó). –

+0

Tại sao bạn mong đợi tăng hiệu suất? Kiểu của cả hai tham số là 'double'. –

+0

Bởi vì nó chỉ sử dụng một thực hiện phép thuật đó là chuyên ngành cho tất cả các đôi; nó không sử dụng bất kỳ phép thuật đặc biệt nào cho sức mạnh số nguyên. Nếu bạn chỉ sử dụng phép nhân trực tiếp ('x * x') bạn sẽ nhận được kết quả tốt hơn. –

Trả lời

10

Bất chấp những sự giảm giá không công bằng, câu hỏi có ý nghĩa nhiều vì nó cho thấy lỗi JVM thực sự.

Khi bạn chạy Oracle JDK hiệu suất của Math.pow(x, 2.0) rất khác nhau giữa các phiên bản JVM.

  • Trước JDK 7u40 Math.pow sử dụng thực hiện các phần mềm, tức là nó chỉ đơn giản là gọi __ieee754_pow chức năng mô phỏng các hoạt động trong phần mềm. Đó là khá chậm, nhưng nó đã có một trường hợp đặc biệt cho y == 2.
  • Kể từ khi JDK 7u40 Math.pow trở thành một JVM nội tại đã được dịch sang hướng dẫn FPU bởi JIT. Tuy nhiên, với tối ưu hóa này trường hợp đặc biệt đã bị mất, dẫn đến hồi quy hiệu suất cho y == 2, xem bug JDK-8029302.
  • Hồi quy hiệu suất này đã được sửa trong JDK 8u25 và 7u80 sắp tới. Vì JDK 8u25 Math.pow hoạt động đủ nhanh cho tất cả các giá trị, nhưng cực kỳ nhanh đối với y == 2. Xem related question.

P.S. Thời gian xấp xỉ tính bằng giây đối với các yêu cầu 100M Math.pow trên máy của tôi với các phiên bản JDK khác nhau.

   Math.pow(x, 2.0) Math.pow(x, 2.0000001) 
JDK 7u25   3.0    30.4 
JDK 7u40   11.1    11.1 
JDK 8u40   0.1    11.1  
+1

Khi bạn nói "triển khai Java", bạn thực sự có nghĩa là phương pháp gốc, đúng không? –

+1

Trích dẫn từ lỗi JDK liên kết: 'Sử dụng" -XX: + UnlockDiagnosticVMOptions -XX: + PrintIntrinsics "cho thấy việc thực hiện nội tại được sử dụng trong cả hai trường hợp.' Vì vậy, thay đổi thực sự chỉ ở bản chất nội tại, không phải trong thực tế là nội tại đã được giới thiệu. –

+2

@MarkoTopolnik Vâng, đó là một nội tại khá ngu ngốc. Tôi có nghĩa là nó không thu thập thông qua tất cả [JNI thứ] (http://stackoverflow.com/a/24747484/3448419) (theo nghĩa này nó là một * "nội tại" *), nhưng nó vẫn phải làm cho một người bản địa gọi hàm thi đua.Trong JDK7u40 nó đã trở thành một * "thực sự nội tại" *, tức là việc thực hiện được viết trong hội đồng và được inlined vào người gọi. Tôi đã cập nhật câu trả lời để chính xác hơn. Cảm ơn bạn đã đánh giá :) – apangin

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