2012-01-13 27 views
7

cho các tuyên bố sau đó được thực hiện rất nhiều:điều kiện vs bộ phận

iNormVal = iVal/uRatio; 

sẽ sau có ý nghĩa hơn (hiệu suất khôn ngoan) nếu uRatio == 1 nhất (90%) của thời gian?

if(uRatio > 1) 
iNormVal = iVal/uRatio; 
else 
iNormVal = iVal; 

nhờ ..

+2

Bạn có thể cấu hình nó. – kennytm

+1

Là các giá trị số nguyên hoặc đôi hoặc nổi? –

+0

@Ed tiền tố i là int, u là unsigned int – nantonop

Trả lời

4

Bạn cần phải profile này để có được một phép đo, nó quá khó đoán. Trình biên dịch có thể quyết định bạn đã sai và xóa thử nghiệm, vì vậy hãy kiểm tra và không tối ưu hóa.

Chi phí thực tế của một bộ phận (số nguyên) có thể khá thấp, đặc biệt là trên các bộ vi xử lý hiện đại dành cho máy tính để bàn. Theo số this PDF, chi phí trên cầu hiện đại (Wolfdale/Nehalem/Sandy Bridge) của bộ phận 32/32-bit tương ứng là 14-23/17-28/20-28. Vì vậy, nếu bạn thực sự làm điều này rất nhiều, nó có thể tăng lên. Trong trường hợp đó, hãy xem xét các tùy chọn song song (vectơ hóa) nếu có thể.

Tôi sẽ cố gắng tránh nó nếu có thể, vì nó giới thiệu một chi nhánh. Các nhánh có hai nhược điểm: chúng làm cho mã phức tạp hơn bằng cách giới thiệu nhiều đường dẫn mà lập trình viên đọc mã phải hiểu, và chúng cũng có thể giới thiệu chi phí thực thi.

+0

+1, phân nhánh ít hơn có nghĩa là mã đơn giản và dễ hiểu hơn. –

+0

không thể đồng ý hơn nói chung, đã xem xét điều này vì tôi nghĩ rằng nó không thực sự gây nhầm lẫn mã và sẽ được thực hiện rất nhiều. profiling sẽ nói, cảm ơn. – nantonop

2

Điều đó tùy thuộc.

Mã có trong ứng dụng quan trọng về hiệu suất không? Nếu vậy thì nó có thể giúp hoàn thiện khôn ngoan. Nếu không tốt sau đó tôi thường sẽ sai về phía hoặc đọc được và không giới thiệu thêm nếu tuyên bố.

Ngay cả khi nó đang ở trong một ứng dụng quan trọng hiệu suất, nó thường là các tương tác ranh giới bên ngoài chiếm 95% thời gian hoàn thiện như tương tác với cơ sở dữ liệu hoặc dịch vụ bên ngoài. Các trình biên dịch thường thực thi rất nhanh và nếu các câu lệnh rất rẻ. Khi chúng tôi thường cấu hình mã của chúng tôi, hiếm khi chúng tôi thực hiện thay đổi như những gì bạn đã mô tả chỉ vì lý do hoàn hảo. Việc sử dụng sai vòng lặp và các loại tương tự đôi khi có thể chống đỡ nhưng chúng tôi hiếm khi thêm các câu lệnh như được mô tả.

Hope this helps ...

7

Vì bạn phát hiện điều này như một nút cổ chai tiềm năng, đó là rất khả năng vị trí này là hoàn toàn không liên quan cho tốc độ tổng thể của ứng dụng. Nghiêm túc, con người, ngay cả lập trình viên guru, nổi tiếng là xấu khi phát hiện các tắc nghẽn thực sự. (Sự khác biệt là lập trình viên tốt thừa nhận và rao giảng rằng, trong khi đàn em giữ dành thời gian để tối ưu hóa các điểm không thích hợp.)

Nói chung tôi thấy phương pháp này để tối ưu hóa hữu ích nhất:

  1. Nếu tốc độ là một mối quan tâm lớn, lên lịch thời gian đáng kể để tối ưu hóa được thực hiện trước khi phát hành ứng dụng của bạn.
  2. Thiết kế mã của bạn để mã không thể bi quan vốn có thể thao.
  3. Triển khai cách dễ nhất để hiểu mã. Ngăn chặn sự bi quan rõ ràng (giống như truyền tham số theo giá trị thay vì tham chiếu), nhưng không được quá mức.
  4. Kiểm tra nếu quá chậm.Nếu có hồ sơ ứng dụng và xác định các điểm nóng.
  5. Đặt tài nguyên thành tối ưu hóa (và do đó có khả năng làm xáo trộn) những điểm nóng đó, định dạng lặp lại để kiểm tra xem những thay đổi nào có thể trợ giúp.
  6. Dừng khi ứng dụng đủ nhanh.

(Nó khác cho mã thư viện, rõ ràng, nhưng những vài bước sẽ mang bạn một chặng đường dài.)

+0

Tôi đồng ý, nhưng bức tranh lớn mà bạn mô tả dường như không đủ lý do để tránh làm nhòe thứ gì đó trong mã của bạn sẽ cải thiện perf (nếu perf là ​​thứ bạn muốn và nếu bạn chắc chắn nó sẽ cải thiện). Tôi không nói về một thay đổi lớn ở đây và tôi không thiết lập tắc nghẽn .. mà nói cảm ơn cho bài viết của bạn và tôi phải nói tôi đồng ý .. – nantonop

+1

@nantonop: Vấn đề là bạn * không * chắc chắn điều này sẽ cải thiện hiệu suất, và trong tất cả khả năng nó sẽ không. –

+2

@nantonop: Lý do để tránh tối ưu hóa vô nghĩa là ___ 1) ___ nó rút tài nguyên cần thiết để tối ưu hóa các điểm đếm và ___ 2) ___ nó có thể [giới thiệu các lỗi tinh tế] (http://stackoverflow.com/questions/8848167/ điều kiện-vs-bộ phận # comment-11051422). – sbi

2

Nếu bạn quyết định đi với phân nhánh sau đó bạn có thể kiểm tra đầu tiên đối với trường hợp chung. Nó có thể đọc được nhiều hơn một chút và nên có hiệu năng tốt hơn một chút.

if(uRatio <= 1) { 
    iNormVal = iVal; 
} 
else { 
    iNormVal = iVal/uRatio; 
} 

Để dễ đọc hơn, bạn có thể thêm biến cục bộ có tên tốt chứa kết quả biểu thức.

unsigned int uSmallRatio = uRatio <= 1; 
if(uSmallRatio) { 
    iNormVal = iVal; 
} 
else { 
    iNormVal = iVal/uRatio; 
} 

Trình biên dịch có thể tối ưu hóa mã này vào cùng một mã máy như cách tiếp cận đầu tiên. Tôi không chắc chắn về điều này mặc dù.

Tương tự như vậy bạn có thể làm điều này không nhưng nó là đẹp:

iNormVal = uRatio <= 1 ? iVal : iVal/uRatio; 

Cuối cùng cách tiếp cận khác sẽ là:

iNormVal = iVal; 
if(uRatio > 1) { /*explain why you do this so it won't be changed by somebody else*/ 
    iNormVal = iVal/uRatio; 
} 

tôi chắc chắn rằng có những cách tiếp cận khác để xem xét.

Kính trọng ...

1

Điều khoản if thực sự có khả năng sẽ làm cho chương trình chậm hơn. Phân nhánh là thực sự kém hiệu quả vì bộ vi xử lý hiện đại là pipelined và các chi nhánh ngăn không cho đường ống hoàn toàn hiệu quả. Đây là một vấn đề quan trọng như vậy mà nỗ lực đáng kể đi vào branch prediction, nhưng điều đó sẽ không giúp ích gì trong trường hợp này. Ngay cả khi dự đoán là đúng 90% thời gian, điều đó có nghĩa là một đường ống trống 10% thời gian, điều này còn tệ hơn nhiều so với phân chia int (đặc biệt là khi tính đến mệnh đề if sẽ mất thời gian).

Nhưng rất có thể nó không quan trọng chút nào vì mã của bạn dành phần lớn thời gian của nó ở một nơi hoàn toàn khác, khiến cho toàn bộ câu hỏi này lãng phí rất nhiều thời gian.

+0

Bạn chắc chắn đúng về mặt lý thuyết. Nhưng phân nhánh này có thể chỉ là một vài byte mã máy, vì vậy trong thực tế nó có thể không quan trọng chút nào. _If_ bạn muốn biết điều này, bạn thực sự cần phải đo lường và so sánh (và lưu ý rằng điều này có thể rất khác nhau từ nền tảng đến nền tảng). Nhưng đó thực sự chỉ là vấn đề rắc rối nếu bạn biết ngay cả vị trí này. – sbi

1

Hầu hết các vấn đề về hiệu suất đều là hệ tư tưởng (bạn thiết kế sai cách) hoặc triển khai thuật toán chậm hơn đã được chứng minh (các lựa chọn nhất định).

Ngoài ra, hiệu suất đạt được sẽ ở cấp độ lắp ráp và sẽ phụ thuộc vào nền tảng.

Tôi khó có thể đề nghị điều này như là một mối quan tâm thực tế cho hiệu suất, trừ khi bạn thực sự bị ràng buộc về hiệu suất, tại thời điểm đó bạn cần phải kiểm tra ở trên đầu tiên.

Tất cả những gì bạn đã làm là nâng cao lông mày của người sẽ duy trì mã của bạn. Hy vọng bạn có một lập trình viên lười biếng để lại một mình, hoặc bạn sẽ mất mã này.

Vì bạn không có bảo đảm ở cấp độ này, mã sẽ hoạt động như thế nào trên các nền tảng khác nhau cho các trình biên dịch, tùy chọn trình biên dịch và tối ưu hóa khác nhau, thậm chí bạn có thể mất mã để tối ưu hóa trình biên dịch. Tốt nhất là tập trung vào các vấn đề lớn hơn.

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