Phần mềm khoa học nên được tối ưu hóa bao nhiêu?


13

Đối với các ứng dụng yêu cầu tài nguyên tính toán đáng kể, hiệu suất cao có thể là một yếu tố quan trọng khi mang lại kết quả khoa học hoặc đạt được "đột phá" trong thời gian hợp lý.

Các nhà phát triển phần mềm nên đầu tư bao nhiêu thời gian và công sức vào việc tối ưu hóa một ứng dụng? Các tiêu chí quan trọng được sử dụng là gì?


Các chương trình mà các nhà khoa học viết thường chạy trong một thời gian rất dài (ví dụ như mô phỏng). Thời gian lập trình viên và thời gian chạy máy tính có thể tương đương nhau. Điều này rất khác với công việc lập trình viên "thông thường" ngày nay. Giống như trong những ngày đầu của máy tính, thường đáng để đầu tư một số nỗ lực (và thời gian lập trình viên) để làm cho mô phỏng nhanh hơn và hoàn thành nhanh hơn và hoàn thành công việc nhanh hơn.
Szabolcs

Câu trả lời:


15

Trong phần lớn các trường hợp, các cải tiến về thuật toán tạo ra sự khác biệt lớn hơn so với cải tiến về tối ưu hóa. Các thuật toán cũng dễ mang theo hơn các tối ưu hóa ở mức độ thấp. Lời khuyên của tôi là tuân theo các thực tiễn tốt nhất chung về cách bố trí bộ nhớ để sử dụng lại bộ đệm, tránh sao chép hoặc giao tiếp quá mức, xử lý hệ thống tệp theo cách lành mạnh và làm cho các hạt nhân dấu phẩy động có đủ độ chi tiết để vector hóa. Đôi khi điều này là đủ để đạt được một phần "đỉnh" cao chấp nhận được (đối với thao tác này).

Luôn phác thảo một mô hình hiệu suất cho các hoạt động mà bạn nghĩ là quan trọng (hoặc bạn khám phá là quan trọng bằng cách định hình). Sau đó, bạn có thể sử dụng mô hình hiệu suất để ước tính những gì một triển khai được điều chỉnh cao có thể mang lại. Nếu bạn quyết định rằng speedup là xứng đáng (so với những thứ khác bạn có thể làm), thì hãy tối ưu hóa.

Có lẽ thách thức khó khăn nhất là thiết kế mức cao, quan trọng (theo nghĩa là rất nhiều mã sẽ phụ thuộc vào các lựa chọn này) giao diện và cấu trúc dữ liệu để bạn có thể tối ưu hóa sau này mà không cần thay đổi API. Ngược lại với tối ưu hóa cụ thể và hướng dẫn chung, tôi không biết cách dạy điều này ngoại trừ thông qua kinh nghiệm. Làm việc với phần mềm nguồn mở nhạy cảm với hiệu suất. Như với bất kỳ quyết định API nào, điều quan trọng là phải hiểu không gian vấn đề.


1
Gần đây tôi đã có một hệ số cải thiện 10.000 (cho các sự kiện lớn nhất của chúng tôi) trong thời gian chạy một bước giới hạn trong phân tích của chúng tôi chỉ là thay thế một thuật toán O (n ^ 2) theo thời gian và không gian bằng một O (n log n ) ở cả hai. Hãy nhớ rằng nó có nghĩa là một sự phụ thuộc khác và một số phức tạp được thêm vào, nhưng đôi khi nó đáng giá ...
dmckee --- người điều hành cũ mèo con

1
Các yếu tố tăng tốc (liên quan đến một cái gì đó) không đáng để tham khảo rõ ràng về những gì bạn có so với. Nếu bạn so sánh với một triển khai xấu dựa trên một thuật toán không phù hợp và sau đó thay đổi thì rõ ràng sẽ không hợp lý khi mong đợi lợi nhuận tương đối lớn.
Allan P. Engsig-Karup

1
@ Allan: Có một yếu tố 10.000 để có được từ một thay đổi duy nhất thì rõ ràng đó là một triển khai không được chọn. Mã trước đó bị tổn thương nhiều bởi không gian không cần thiết cũng như độ phức tạp của thời gian: hiệu năng bộ nhớ đệm rất tệ. Nhưng đó không phải là vấn đề phải không?
dmckee --- ex-moderator mèo con

8

Làm thế nào bạn sẽ xác định "tối ưu hóa"? Có toàn bộ phổ từ việc phát triển các thuật toán tốt hơn hoặc các mô hình tính toán cho đến sử dụng trình biên dịch điều chỉnh bằng tay.

Theo quan điểm và kinh nghiệm của tôi, trái cây treo thấp nằm ở đâu đó ở giữa, ví dụ: chọn một thuật toán phù hợp nhất với kiến ​​trúc máy tính cơ bản. Thuật toán không nhất thiết phải là tiểu thuyết và sự hiểu biết của bạn về kiến ​​trúc cơ bản không nhất thiết phải rất cụ thể, ví dụ:

  • Nếu bạn biết rằng kiến ​​trúc của bạn hỗ trợ SIMD, hãy cấu trúc lại phép tính sao cho các hoạt động của bạn có thể được viết theo các vectơ ngắn,
  • Nếu bạn biết kiến ​​trúc của bạn là một máy tính đa lõi, hãy thử chia nhỏ nhiệm vụ tính toán của bạn thành các tác vụ phụ riêng lẻ không can thiệp lẫn nhau và chạy chúng song song (nghĩ DAG về các tác vụ phụ của bạn) ,
  • Nếu kiến ​​trúc cơ bản của bạn có GPU, hãy nghĩ đến các cách bạn có thể định dạng lại tính toán của mình dưới dạng một nhóm các luồng di chuyển qua dữ liệu theo bước khóa,
  • Vân vân...

Tất cả các tính năng trên, ví dụ như SIMD, song song và GPU, có thể được truy cập mà không cần nhiều kiến ​​thức cấp thấp, nhưng chỉ thực sự mang lại lợi thế trong các thuật toán có thể dễ dàng khai thác chúng.


4

Tôi đồng ý với tất cả các câu trả lời đã được đưa ra cho đến nay ... Tôi chỉ muốn giải quyết một khía cạnh bị bỏ qua khác của tối ưu hóa mã: kỳ vọng chất lượng.

Vấn đề tối ưu hóa mã thường phát sinh khi người dùng cố gắng giải quyết các vấn đề lớn hơn và lớn hơn và mã không đủ để đáp ứng nhu cầu / mong đợi của người dùng. Lượng thời gian mà một người nên đầu tư vào tối ưu hóa mã phụ thuộc vào nhu cầu để đáp ứng kỳ vọng này. Chắc chắn đầu tư thời gian đáng kể nếu có nhu cầu quan trọng cho lợi thế cạnh tranh (ví dụ: hoàn thiện & xuất bản nghiên cứu của bạn về một chủ đề nóng trước những người khác).

Tất nhiên, nên đầu tư bao nhiêu thời gian tùy thuộc vào tốc độ bạn cần đến và mức độ di động mà bạn muốn mã. Thông thường, hai nhu cầu này mâu thuẫn với nhau và bạn phải quyết định cái nào quan trọng hơn trước khi bạn bắt đầu tối ưu hóa. Bạn càng muốn di động, bạn càng phải dựa vào các thay đổi thiết kế cấp cao đối với mã (thuật toán / cấu trúc dữ liệu). Bạn muốn mã nhanh hơn để thực hiện, nó phải được điều chỉnh với tối ưu hóa mức thấp cụ thể cho một máy cụ thể (ví dụ: tối ưu hóa mã / trình biên dịch / thời gian chạy).


4

Bạn sẽ phải thực hiện phân tích (chi phí) chi tiêu rất nhiều tháng (và những điều đó luôn hoang đường :-)) để đạt được tốc độ thực hiện. Bạn sẽ phải tính xem phần mềm này sẽ được sử dụng bao nhiêu lần và bao nhiêu người để bạn có thể ước tính mức tăng.

Quy tắc của ngón tay cái, như mọi khi, là quy tắc 80/20 nổi tiếng. Tại một số thời điểm, nó không tăng thêm nữa để dành nhiều thời gian hơn để đạt được vài phần trăm (hoặc ít hơn) thời gian chạy. Nhưng bạn sẽ phải phân tích.

Và tôi chân thành đồng ý với các áp phích trên: đảm bảo API của bạn được suy nghĩ kỹ để nó không cần nhiều thay đổi và đảm bảo mã có thể mang theo và có thể duy trì được (nghĩ về việc phải phân tích lại thuật toán bạn đã viết và nitty-gritty tối ưu hóa mười năm trước). Và chắc chắn rằng bạn sử dụng thực hành lập trình tốt và thư viện chuẩn. Rất có thể là hợp lý ai đó đã nghĩ về thuật toán hiệu quả nhất cho ứng dụng của bạn.

Để trích dẫn Donald Knuth: "tối ưu hóa sớm là gốc rễ của mọi tội lỗi". Vì vậy, hồ sơ mã của bạn, nhưng không quá sớm.


Bạn đang đề cập đến quy tắc Pareto (80/20)? Nếu vậy, bạn có nghĩa là chúng ta nên tập trung nỗ lực tối ưu hóa vào 20% mã tạo ra 80% chậm lại? Hay bạn có nghĩa là nếu bạn chỉ có thể mong đợi tăng tốc 20%, thì nó không đáng để tối ưu hóa?
Paul

Không, tôi chỉ sử dụng nó như một loại nguyên tắc, không chính xác là 80/20. Tại một số thời điểm, bạn sẽ dành rất nhiều nỗ lực để chỉ đạt được một vài phần trăm mà không còn nỗ lực nữa.
GertVdE

3

Một số lời khuyên bổ sung:

  1. Trước khi thực hiện bất kỳ tối ưu hóa chương trình làm việc nào, hãy đảm bảo bạn có một bộ trường hợp kiểm thử tốt giúp duy trì tính toàn vẹn của mã. Không có điểm nào nhận được kết quả sai nhanh hơn.
  2. Nếu tối ưu hóa của bạn làm cho mã ít đọc hơn, hãy giữ phiên bản gốc xung quanh, ít nhất là dưới dạng nhận xét, nhưng tốt hơn là phiên bản thay thế sẽ được chọn vào thời gian biên dịch và thời gian chạy. Nhu cầu tối ưu hóa của bạn có thể thay đổi khi các vấn đề của bạn và máy móc của bạn phát triển và mã gốc có thể là điểm khởi đầu tốt hơn cho việc tối ưu hóa bạn sẽ thực hiện trong 5 năm kể từ bây giờ.
  3. Nếu phiên bản tối ưu hóa của bạn hóa ra có tác động tối thiểu, nhưng làm cho mã ít đọc hơn, ít phổ biến hơn hoặc kém ổn định hơn, hãy quay lại phiên bản gốc. Bạn mất nhiều hơn bạn đạt được.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.