2012-01-20 38 views
6

Java Compiler sẽ tối ưu hóa hoạt động toán học lặp đi lặp lại đơn giản như:Trình biên dịch có tối ưu hóa phép tính toán lặp lại không?

if (prevX/width != curX/width) { 
    // Do something with prevX/width value 
} else { 
    // Do something with curX/width value 
} 

Tôi biết tôi chỉ có thể gán kết quả cho một biến trước khi câu lệnh if, và trả lại các biến, nhưng nó là loại cồng kềnh. Nếu trình biên dịch tự động nhận ra rằng các tính toán tương tự đang được thực hiện và lưu trữ các kết quả vào các biến tạm thời trên riêng của nó, tôi muốn dính vào quy ước trên.

* Chỉnh sửa - Tôi là kẻ ngốc. Tôi đã cố gắng đơn giản/trừu tượng câu hỏi của mình quá nhiều. Nó không đơn giản như: if (x> y)

+1

trừ khi chiều rộng có thể là âm, bạn không thể chỉ cần 'if (x> y) ...' – user949300

+1

Tại sao không chỉ 'Math.max (x/width, y/width)'? Ngoài ra @ user949300: nếu đây là ints, nó có thể đưa ra một kết quả khác. –

+0

@Eric Andres Tôi không nghĩ rằng ints sẽ quan trọng trong vấn đề ban đầu được trình bày, vì nó chỉ là kiểm tra 2 chiều (nó không kiểm tra sự bình đẳng) Nếu (x> y), không có cách nào x/chiều rộng 0. Nhưng ints sẽ quan trọng rất nhiều trong câu hỏi mới, vì vậy +1 cho bạn. – user949300

Trả lời

7

Câu trả lời là có. Điều này được gọi là Common Subexpression Elimination và là một tối ưu hóa (và mạnh mẽ) tối ưu hóa trình biên dịch được sử dụng trong Java, C/C++ và các ...

This page xác nhận rằng HotSpot JVM sẽ thực hiện tối ưu hóa này.


Điều đó cho biết, trình biên dịch/thời gian chạy có thể thực hiện tối ưu hóa này khi bạn mong đợi nó là một câu chuyện khác hay không. Vì vậy, tôi thường thích tự mình tối ưu hóa hơn nếu nó cũng tăng cường khả năng đọc.

double xw = x/width; 
double yw = y/width; 

if (xw > yw) { 
    return xw; 
} else { 
    return yw; 
} 
+1

+1: Trình biên dịch 'javac' không có sự tối ưu, tuy nhiên trình biên dịch bản địa JIT có khả năng thực hiện điều này với giả định nó biên dịch mã (hầu hết mã không được biên dịch thành native bởi vì nó không đủ chạy) –

2

Nói chung, "có" - trình biên dịch sẽ tối ưu hóa mã nếu có thể và HotSpot JVM cũng có thể cải thiện khối mã lặp đi lặp lại.

Trong trường hợp này tuy nhiên, bạn sẽ được tốt hơn để cấu trúc lại các mã như thế này:

if (x > y) 
    return x/width; 
return y/width; 

mà tránh hoạt động một bộ phận nếu x > y.

+0

Tôi chỉ muốn thêm rằng dựa vào tối ưu hóa trình biên dịch và các tính năng không có giấy tờ khác không phải là một thực hành lập trình tốt. Cho dù kết quả có giống nhau hay không, việc viết mã hiệu quả luôn nâng cao chất lượng mã. – buc

+0

@buc ​​99% mã bạn viết không có hiệu suất nhạy cảm và thường không phải mã hiệu quả nhất không phải là mã duy trì được nhiều nhất. Đặc biệt với những trình biên dịch tốt như thế nào những ngày này đáng lo ngại liệu họ sẽ làm CSE trên một chức năng toán học đơn giản như thế này là vô ích. Chỉ cần viết mã rõ ràng hơn .. – Voo

3

Trình biên dịch có thể thực hiện các tối ưu hóa như vậy. Cho dù nó thực sự làm phụ thuộc vào câu trả lời cho sau:

là trình biên dịch phép để làm điều này bằng JLS?

Trong một số trường hợp thì không. Ví dụ: nếu prevX là một biến thể hiện volatile, thì nó phải được tìm nạp từ bộ nhớ mỗi khi mã nguồn cho biết nó được sử dụng. Một trường hợp khác là khi biểu thức con thường gặp liên quan đến một cuộc gọi phương thức với một hiệu ứng phụ có thể quan sát được; tức là một nơi khác trong chương trình có thể có thể cho biết liệu phương pháp được gọi một lần hay hai lần.

Trình biên dịch có khả năng làm việc này không?

Trình biên dịch cần phân tích mã để phát hiện các biểu thức phụ phổ biến có thể được tối ưu hóa một cách hợp pháp. Có hai vấn đề ở đây:

  • Trình biên dịch có khả năng thực hiện các lý do cần thiết không? Ví dụ, người ta có thể giả thuyết một trình biên dịch có thể xác định rằng một cuộc gọi phương thức cụ thể sẽ có tác dụng phụ miễn phí và do đó có thể được tối ưu hóa. Tuy nhiên, việc xây dựng trình biên dịch thực sự có khả năng làm việc này là ...và vấn đề thú vị.

  • Tối ưu hóa có đáng giá không? Có một sự cân bằng giữa chi phí thực hiện tối ưu hóa và các lợi ích. Nó không phải là một thương mại thẳng về phía trước. Nó cần phải tính đến chi phí tìm kiếm để xem liệu một tối ưu hóa có thể được thực hiện ... khi nó thực sự không thể. Nói cách khác, tác động đến thời gian biên dịch. (Bear và nhớ rằng trong Java tối ưu hóa chủ yếu được thực hiện tại thời gian chạy bởi trình biên dịch JIT ... do tác động này trên hiệu suất ứng dụng.)

Trong một ví dụ đơn giản như của bạn, tối ưu hóa là hợp pháp (modulo volatile) và người ta sẽ mong đợi một trình biên dịch JIT nửa phong nha để thực hiện nó.


Một câu hỏi khác là liệu bạn nên cố gắng giúp trình biên dịch bằng cách đánh giá các biểu thức thông thường một cách rõ ràng mã của bạn và gán kết quả cho là tạm thời.

IMO, câu trả lời thường là không.

  • Trình biên dịch tốt có thể sẽ hoạt động tốt như bạn. Và nếu không, thế hệ tiếp theo có thể làm.

  • Mã có thể không đảm bảo tối ưu hóa tay. Trừ khi bạn đã lược tả mã của mình để xác định nơi bị tắc nghẽn, tối ưu hóa tay của bạn có khả năng là không liên quan đến hiệu suất ứng dụng thực tế ... và lãng phí thời gian của bạn.

  • Có khả năng bạn sẽ nhồi nhét nó; ví dụ. bằng cách quên rằng cuộc gọi phương thức có tác dụng phụ quan trọng hoặc biến là volatile vì một lý do chính đáng.

Mặt khác, nếu viết lại làm cho mã của bạn dễ đọc hơn , đó là một lý do chính đáng để làm điều đó.

+0

+1 cho câu trả lời chi tiết. – Mysticial

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