Khi nào là thời điểm tốt để lý giải về hiệu suất trong Haskell?


8

Chính Simon Peyton Jones nhận ra rằng lý do về hiệu suất trong Haskell là khó khăn do ngữ nghĩa không nghiêm ngặt.

Tôi vẫn chưa viết một dự án quan trọng bằng haskell vì vậy tôi tự hỏi: tôi có thể suy luận về hiệu suất khi bắt đầu dự án (khi chọn cấu trúc dữ liệu cơ bản & thư viện IO) và bất cứ khi nào có vấn đề phát sinh, hãy giải quyết nó với trình lược tả?

Nói cách khác, có thể (nghĩa là không quá đau đớn) để trì hoãn việc xử lý hiệu suất khi bạn gặp vấn đề về hiệu năng hoặc bạn phải học cách dự đoán GHC sẽ chạy mã của bạn như thế nào (ví dụ: suy luận xem bộ phân tích nghiêm ngặt sẽ quyết định điều gì )?


Khi hiệu suất quan trọng.
Thomas Eding

Câu trả lời:


7

Các câu trả lời khác cung cấp lời khuyên rộng rãi về lý luận hiệu suất. Câu trả lời này đặc biệt đề cập đến ngữ nghĩa không nghiêm ngặt.

Mặc dù sự lười biếng làm cho việc suy luận về hiệu suất trở nên khó khăn hơn, nhưng nó không phức tạp như bạn nghĩ. Mặc dù sự lười biếng khá hữu ích trong một số tình huống, hầu hết thời gian một ngôn ngữ lười biếng được sử dụng theo cùng một cách mà một ngôn ngữ nghiêm ngặt sẽ được sử dụng. Do đó, lý luận hiệu suất cho các ngôn ngữ nghiêm ngặt có thể được áp dụng (với một vài điều chỉnh) cho các ngôn ngữ lười biếng.

Về mặt phức tạp thời gian, đánh giá háo hức thực hiện công việc nhiều hơn so với đánh giá lười biếng. Cả hai chiến lược tạo ra kết quả như nhau trong hầu hết các trường hợp. . Trong những tình huống không thường xuyên xảy ra khi sự lười biếng, ước tính này sẽ quá cao và nên được điều chỉnh xuống.

Mặc dù đánh giá lười biếng mang lại cho bạn độ phức tạp thời gian thấp hơn so với đánh giá háo hức, đôi khi nó mang lại cho bạn độ phức tạp không gian cao hơn, tức là rò rỉ không gian. Độ phức tạp không gian cao hơn có thể được sửa chữa bằng cách thêm các chú thích nghiêm ngặt để làm cho chương trình thực thi háo hức hơn. Công cụ định hình là khá tốt trong việc theo dõi nguyên nhân rò rỉ không gian. Tôi phân loại điều này là gỡ lỗi chính xác hoặc gỡ lỗi hiệu năng, tùy thuộc vào mức độ nghiêm trọng.


In terms of time complexity, eager evaluation does strictly more work than lazy evaluation. Bạn dựa trên cơ sở nào để khẳng định điều đó? Giả sử rằng đánh giá háo hức sẽ chấm dứt tại cùng một điểm với đánh giá lười biếng (nghĩa là không đánh giá lười biếng các chuỗi vô hạn và những thứ tương tự), thuật toán tạo háo hức sẽ luôn nhanh hoặc nhanh hơn (nghĩa là làm ít việc hơn) một thuật toán lười biếng vì nó không yêu cầu chi phí của các cuộc gọi lặp lại thành thói quen của trình tạo.
Mason Wheeler

2
Tôi nghĩ lý do tôi yêu các bạn Haskell là vì tôi chỉ không hiểu bạn đang nói về điều gì.
Erik Reppen

3
@MasonWheeler: Ông của hầu như nói về tiệm cận phức tạp. Các yếu tố không đổi là một vấn đề thực hiện. Hơn nữa, ngay cả khi cả hai chương trình chấm dứt, chương trình không nghiêm ngặt có thể thực hiện công việc ít hơn đáng kể: xem xét all even [1..1e10]cho cả phiên bản nghiêm ngặt và phiên bản lười biếng all. Trình biên dịch cũng có nhiều thời gian hơn để chọn thứ tự đánh giá trong một ngôn ngữ như Haskell với những thứ như hợp nhất vòng lặp.
Tikhon Jelvis

1
@MasonWheeler Đánh giá lười biếng tránh đánh giá bất kỳ điều khoản nào không cần thiết. Tôi không thể tìm thấy một tài liệu tham khảo có thẩm quyền, nhưng đây là một chỉ ra rằng đánh giá lười biếng thực hiện giảm ít hơn so với đánh giá háo hức: en.wikibooks.org/wiki/Haskell/ Lỗi
Heatsink

1

Tối ưu hóa những thứ lớn trước khi bạn viết mã và những thứ nhỏ khi bạn hoàn thành.

Ví dụ, trước khi bắt đầu viết mã, bạn nên suy nghĩ về những điều sau:

  • Các thư viện / khung công tác mà bạn sẽ sử dụng có nhanh không?
  • Cố gắng giữ cấu trúc dữ liệu của bạn đơn giản.
  • Cố gắng giữ cho các thuật toán và các mẫu thiết kế của bạn đơn giản nhất có thể.
  • Ngôn ngữ tôi đang sử dụng nhanh như thế nào?

...và như thế.

Sau đó, khi bạn sắp hoàn thành mã của mình, hãy nghĩ về những điều nhỏ như chức năng tích hợp nào nhanh hơn, tôi có nên viết lại vùng mã đó để làm cho nó hiệu quả hơn, v.v.

Điều này đúng với bất kỳ ngôn ngữ nào và nó thực sự phụ thuộc vào loại phần mềm bạn đang viết. Haskell là một ngôn ngữ có mục đích chung, vì vậy bạn có thể (sửa tôi nếu tôi sai) không làm bất cứ điều gì cần phải cực kỳ nhanh. Nếu vậy, bạn nên sử dụng ngôn ngữ cấp thấp hơn. Nếu tốc độ là một vấn đề, nhưng không đủ để bạn nên sử dụng ngôn ngữ cấp thấp, thì bạn nên tối ưu hóa hiệu suất của mình dựa trên những điều trên.

Tất nhiên, mọi người đều làm những việc khác nhau, vì vậy nếu kinh nghiệm cá nhân của bạn khiến bạn nghĩ rằng bạn nên làm điều đó khác nhau dựa trên tình huống của bạn, thì có lẽ bạn nên làm.


5
Vấn đề là trong hầu hết các ngôn ngữ, tôi có thể dễ dàng suy luận về hành vi thời gian chạy. Trong haskell, điều này khó hơn nhiều. Vì vậy, một người có nhiều khả năng thực hiện một cách tiếp cận sai, và để tăng xác suất lỗi nước hoa.
Simon Bergot

Câu trả lời bắt đầu tốt đẹp, sau đó bạn nói "xem những điều nhỏ có thể được cải thiện" ... vâng, không. Hồ sơ.
Florian Margaine

3
Câu trả lời này quá rộng và không hữu ích cho Haskell. Giả sử OP đã biết về tối ưu hóa macro và vi mô. Làm thế nào để câu trả lời này áp dụng cho Haskell , một ngôn ngữ không nghiêm ngặt mà khó lý luận hơn về hiệu năng thời gian chạy và bộ nhớ?
Andres F.

@FlorianMargaine Hồ sơ?
Năng động

0

Tôi muốn thêm vào câu trả lời của Dynamic:

  • Làm cho mã của bạn mô-đun và ghép lỏng lẻo .
  • Ẩn chi tiết thực hiện các mô-đun của bạn.

Khi bạn nhận ra sau này trong quá trình phát triển những gì tắc nghẽn mã của bạn, có thể thực sự đau đớn khi cấu trúc lại toàn bộ dự án. Nếu mã của bạn được cấu trúc tốt, các nút cổ chai sẽ dễ dàng tìm thấy hơn và để tối ưu hóa / sửa chữa.

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.