-calculus: Hiệu quả nhất trong biểu diễn bộ nhớ của các chức năng là gì?


9

Tôi muốn so sánh hiệu suất của các cấu trúc dữ liệu được mã hóa (Church's / Scott) với các cấu trúc dữ liệu được mã hóa theo kiểu cổ điển (trình biên dịch / C).

Nhưng trước khi làm điều đó tôi cần biết mức độ hiệu quả của / có thể là biểu diễn chức năng trong bộ nhớ. Tất nhiên chức năng có thể được áp dụng một phần (hay còn gọi là đóng).

Tôi quan tâm đến cả thuật toán mã hóa hiện tại sử dụng các ngôn ngữ chức năng phổ biến (Haskell, ML) và cũng là ngôn ngữ hiệu quả nhất có thể đạt được.


Điểm thưởng: Có mã hóa như vậy mà ánh xạ hàm số được mã hóa thành số nguyên gốc ( short, intv.v. trong C). Nó thậm chí có thể?


Tôi đánh giá hiệu quả dựa trên hiệu suất. Nói cách khác, mã hóa càng hiệu quả thì nó càng ít ảnh hưởng đến hiệu suất tính toán với các cấu trúc dữ liệu chức năng.


Tất cả các nỗ lực Google của tôi đều thất bại, có thể tôi không biết từ khóa phù hợp.
Ford O.

Bạn có thể chỉnh sửa câu hỏi để làm rõ ý của bạn bằng "hiệu quả" không? Hiệu quả cho việc gì? Khi bạn yêu cầu cấu trúc dữ liệu hiệu quả, bạn cần chỉ định thao tác nào bạn muốn có thể thực hiện trên cấu trúc dữ liệu, vì điều đó ảnh hưởng đến việc lựa chọn cấu trúc dữ liệu. Hay bạn có nghĩa là mã hóa càng tiết kiệm không gian càng tốt?
DW

1
Cái này khá rộng. Có rất nhiều máy trừu tượng để tính toán lambda nhằm thực hiện nó một cách hiệu quả (xem ví dụ: SECD, CAM, Krivine's, STG). Trên hết, bạn cần xem xét dữ liệu được mã hóa của Church / Scott, điều này đặt ra nhiều vấn đề hơn. Ví dụ, trong các danh sách được mã hóa của Church, thao tác đuôi phải là O (n) thay vì O (1). Tôi nghĩ rằng tôi đã đọc ở đâu đó rằng sự tồn tại của một mã hóa cho các danh sách trong Hệ thống F với các hoạt động đầu và đuôi O (1) vẫn là một vấn đề mở.
chi

@DW Tôi đang nói về hiệu suất / chi phí chung. Ví dụ, với ánh xạ mã hóa hiệu quả trên danh sách của nhà thờ và danh sách của Haskell sẽ mất cùng thời gian.
Ford O.

Hiệu suất cho (các) hoạt động? Bạn muốn làm gì với các chức năng? Bạn có muốn đánh giá các chức năng này trên một số giá trị? Một lần, hoặc đánh giá cùng một chức năng trên nhiều giá trị? Làm gì khác với họ? Bạn chỉ hỏi làm thế nào để biên dịch một hàm (được viết bằng ngôn ngữ chức năng) để nó có thể được thực thi hiệu quả nhất có thể?
DW

Câu trả lời:


11

Vấn đề là, thực sự không có nhiều thời gian về mặt mã hóa chức năng. Dưới đây là các tùy chọn chính:

  • Viết lại thuật ngữ: bạn lưu trữ các hàm như các cây cú pháp trừu tượng của chúng (hoặc một số mã hóa của chúng. Khi bạn gọi một hàm, bạn duyệt thủ công cây cú pháp để thay thế các tham số của nó bằng đối số. Điều này rất dễ, nhưng không hiệu quả về mặt thời gian và không gian .

  • Đóng: bạn có một số cách biểu diễn một hàm, có thể là cây cú pháp, nhiều khả năng là mã máy. Và trong các hàm này, bạn tham chiếu các đối số của mình bằng cách tham chiếu theo một cách nào đó. Nó có thể là một con trỏ bù, nó có thể là một số nguyên hoặc chỉ số De Bruijn, nó có thể là một tên. Sau đó, bạn biểu diễn một hàm dưới dạng đóng : hàm "hướng dẫn" (cây, mã, v.v.) được ghép nối với cấu trúc dữ liệu chứa tất cả các biến miễn phí của hàm. Khi một hàm thực sự được áp dụng, bằng cách nào đó nó biết cách tìm kiếm các biến miễn phí trong cấu trúc dữ liệu của nó, sử dụng các môi trường, số học con trỏ, v.v.

Tôi chắc chắn có các tùy chọn khác, nhưng đây là những tùy chọn cơ bản và tôi nghi ngờ hầu hết các tùy chọn khác sẽ là một biến thể hoặc tối ưu hóa cấu trúc đóng cơ bản.

Vì vậy, về mặt hiệu suất, các bao đóng hầu như thực hiện tốt hơn so với viết lại thuật ngữ. Trong số các biến thể, cái nào tốt hơn? Điều đó phụ thuộc rất nhiều vào ngôn ngữ và kiến ​​trúc của bạn, nhưng tôi nghi ngờ "mã máy có cấu trúc chứa các vars miễn phí" là hiệu quả nhất. Nó có mọi thứ mà hàm cần (hướng dẫn và giá trị) và không có gì nữa, và việc gọi không kết thúc thực hiện các giao dịch lớn.

Tôi quan tâm đến cả thuật toán mã hóa hiện tại mà các ngôn ngữ chức năng phổ biến (Haskell, ML) sử dụng

Tôi không phải là một chuyên gia, nhưng tôi 99% hầu hết các hương vị ML sử dụng một số biến thể của các bao đóng mà tôi mô tả, mặc dù có khả năng tối ưu hóa. Xem điều này cho một quan điểm (có thể lỗi thời).

Haskell làm một cái gì đó phức tạp hơn một chút vì đánh giá lười biếng: nó sử dụng Viết lại biểu đồ không có thẻ xoay tròn .

và cũng là một trong những hiệu quả nhất có thể đạt được.

Hiệu quả nhất là gì? Không có triển khai nào sẽ hiệu quả nhất trên tất cả các đầu vào, vì vậy bạn có được các triển khai có hiệu quả trung bình, nhưng mỗi triển khai sẽ vượt trội trong các kịch bản khác nhau. Vì vậy, không có thứ hạng nhất định của hầu hết hoặc kém hiệu quả nhất.

Không có phép thuật ở đây. Để lưu trữ một chức năng, bạn cần lưu trữ các giá trị miễn phí của nó bằng cách nào đó, nếu không, bạn đang mã hóa ít thông tin hơn chính chức năng đó. Có thể bạn có thể tối ưu hóa một số giá trị miễn phí với đánh giá một phần nhưng điều đó có rủi ro cho hiệu suất và bạn phải cẩn thận để đảm bảo rằng điều này luôn dừng lại.

Và, có lẽ bạn có thể sử dụng một số loại nén hoặc thuật toán thông minh để đạt được hiệu quả không gian. Nhưng sau đó, bạn hoặc là giao dịch thời gian cho không gian, hoặc bạn đang ở trong tình huống bạn đã tối ưu hóa cho một số trường hợp và làm chậm lại cho những người khác.

Bạn có thể tối ưu hóa cho các trường hợp thông thường, nhưng những gì các trường hợp thông thường có thể thay đổi vào ngôn ngữ, diện tích ứng dụng, vv Các loại mã đó là nhanh chóng cho một trò chơi video (số crunching, vòng chặt chẽ với sự đóng góp lớn) có lẽ là khác nhau hơn những gì nhanh cho trình biên dịch (duyệt qua cây, danh sách công việc, v.v.).

Điểm thưởng: Có mã hóa như vậy mà ánh xạ chức năng mã hóa số nguyên sang số nguyên gốc (ngắn, int vv trong C). Nó thậm chí có thể?

Không, điều này là không thể. Vấn đề là phép tính lambda không cho phép bạn xem xét các điều khoản. Khi một hàm lấy một đối số có cùng kiểu với một chữ số Church, nó cần có khả năng gọi nó, mà không kiểm tra định nghĩa chính xác của chữ số đó. Đó là điều với mã hóa của Giáo hội: điều duy nhất bạn có thể làm với họ là gọi cho họ, và bạn có thể mô phỏng mọi thứ hữu ích với điều này, nhưng không phải là không có chi phí.

Quan trọng hơn, các số nguyên chiếm mọi mã hóa nhị phân có thể. Vì vậy, nếu lambdas được đại diện như số nguyên của họ, bạn sẽ không có cách nào để đại diện cho lambdas không số nhà thờ! Hoặc, bạn sẽ giới thiệu một lá cờ để biểu thị xem lambda có phải là một chữ số hay không, nhưng sau đó, bất kỳ hiệu quả nào bạn muốn có thể được đưa ra ngoài cửa sổ.

EDIT: Kể từ khi viết bài này, tôi đã biết đến một lựa chọn thứ ba để thực hiện các chức năng bậc cao hơn: khử chức năng . Ở đây, mọi lời gọi hàm đều biến thành một switchcâu lệnh lớn , tùy thuộc vào sự trừu tượng hóa lambda nào được đưa ra làm hàm. Sự cân bằng ở đây là đó là một sự chuyển đổi toàn bộ chương trình: bạn không thể biên dịch các phần riêng biệt và sau đó liên kết với nhau theo cách này, vì bạn cần phải có bộ trừu tượng lambda hoàn chỉnh trước thời hạn.

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.