2010-01-05 37 views
9

Tôi đang tìm một vùng chứa cung cấp lặp lại nhanh nhất không theo thứ tự thông qua các phần tử được đóng gói. Nói cách khác, "thêm một lần, lặp lại nhiều lần".Cấu trúc dữ liệu OCaml chuẩn với lặp lại nhanh nhất là gì?

Có một trong số các mô-đun chuẩn của OCaml đủ nhanh (để tối ưu hóa thêm nó sẽ vô dụng)? Hoặc một số loại GPL sẵn sàng của bên thứ ba?

AFAIK không chỉ là một trình biên dịch OCaml, vì vậy các khái niệm về việc nhanh chóng là nhiều hơn hoặc ít rõ ràng ...

... Nhưng sau khi tôi thấy một vài câu trả lời, nó xuất hiện, nó không phải. Tất nhiên, có rất nhiều cấu trúc dữ liệu cho phép lặp lại O (n) thông qua vùng chứa có kích thước n. Nhưng nhiệm vụ tôi giải quyết là một trong số đó, nơi mà sự khác biệt giữa O (n) và O (2n) vấn đề ;-).

Tôi cũng thấy rằng Mảng và Danh sách cung cấp thông tin không cần thiết về thứ tự của các phần tử được thêm mà tôi không cần. Có lẽ trong "thế giới chức năng" có tồn tại các cấu trúc dữ liệu để có thể giao dịch thông tin này cho một chút tốc độ lặp lại.

Trong C, tôi sẽ hoàn toàn chọn một mảng đơn giản. Câu hỏi đặt ra là, tôi nên chọn gì trong OCaml?

+3

1) Để trở thành thực thể, không có sự khác biệt giữa O (n) và O (2n). Bạn đang nói về các yếu tố không đổi. 2) Chọn một thứ tự tùy ý cho các phần tử và sửa nó, như trong một mảng hoặc danh sách, chính xác là cách bạn tối ưu hóa để lặp lại. Làm thế nào để bạn mong đợi để cải thiện về "tăng một chỉ số/theo một con trỏ, lấy từ bộ nhớ" cho tốc độ lặp lại? –

+0

1) Có, tôi đang nói về các yếu tố không đổi, vì tôi đang tối ưu hóa nút cổ chai; 2) Tôi không biết làm thế nào để cải thiện điều đó, nhưng là * nó * cách mô-đun Array và Danh sách hoạt động? Mảng không * nói * (trong khi nó * có thể * được * biết *) để chiếm bộ nhớ liên tiếp. Danh sách cần dereference con trỏ (chậm?). Tôi vẫn còn nghi ngờ. –

+1

@Pavel: Điều Chris đang nói là bạn đang lạm dụng ký hiệu Big O. Anh ta không nói rằng bạn không nên quan tâm đến các yếu tố liên tục, chỉ rằng bạn nên rõ ràng hơn trong ký hiệu toán học của bạn khi đề cập đến chúng. – bcat

Trả lời

8

Bạn không có khả năng làm tốt hơn các mảng và danh sách tích hợp, vì chúng được mã hóa bằng tay trong C, trừ khi bạn liên kết với việc thực hiện bản địa của một trình lặp. Một mảng sẽ hoạt động gần như chính xác như một mảng trong C (một khối liên tục được cấp phát bộ nhớ chứa một chuỗi các giá trị phần tử), có thể với một số con trỏ thừa khác do boxing. Danh sách được thực hiện chính xác như thế nào bạn mong đợi: như các tế bào với một giá trị và một con trỏ "tiếp theo". Mảng sẽ cung cấp cho bạn vị trí tốt nhất cho các loại không được hộp (đặc biệt là float s, trong đó có triển khai siêu hộp không đặc biệt).

Để biết thông tin về việc thực hiện các mảng và danh sách, xem Section 18.3 of the OCaml manual và các tập tin byterun/mlvalues.h, byterun/array.c, và byterun/alloc.c trong mã nguồn OCaml.

Từ người hỏi: thực sự, Array dường như là giải pháp nhanh nhất. Tuy nhiên, nó chỉ hoạt động tốt hơn List thêm 7%. Có lẽ đó là vì loại phần tử mảng không đủ đơn giản: đó là một loại đại số. Hashtbl thực hiện kém hơn 4 lần, như mong đợi.

Vì vậy, tôi sẽ chọn Array và tôi chấp nhận điều này. tốt.

+2

Điều này khá cũ nhưng toàn bộ câu hỏi đã được chuyển lên đầu vì một lý do nào đó. Hãy để tôi lưu ý rằng các danh sách không được mã hóa bằng tay trong C, chúng được định nghĩa như một kiểu dữ liệu đại số thông thường. Modulo một số cú pháp đường cho thuận tiện, nó chỉ là 'loại 'một danh sách = Nil | Nhược điểm của 'a *' một danh sách'. Hiệu năng tốt được giải thích bởi các lựa chọn biểu diễn tốt cho các kiểu dữ liệu OCaml, chứ không phải là chuyên môn hóa. Mảng được xây dựng trong và có địa phương tốt hơn, mặc dù. – gasche

1

Tất cả các cấu trúc dữ liệu chung có thể lặp lại trong thời gian O (n), do đó sự khác biệt giữa cấu trúc dữ liệu sẽ chỉ không đổi (và rất có thể không đáng kể).

Ít nhất danh sách và mảng cho phép lặp lại mà không có chi phí đáng kể. Tôi không thể nghĩ ra một tình huống không đủ nhanh.

3

Mảng - một mảnh bộ nhớ tuyến tính với các mục được truy cập theo thứ tự tuần tự - tốt nhất sử dụng bộ nhớ cache dữ liệu L1 của CPU.

+0

Đó là sự thật trong C ... nó vẫn là nhanh nhất trong OCaml? –

+7

Nếu đó là một kiểu dữ liệu không được hộp (ví dụ: số nguyên), các giá trị mảng sẽ được lưu trữ trong một khối bộ nhớ liền kề. Nếu đó là một kiểu dữ liệu "đóng hộp" (nhất là), thì nó sẽ là một mảng con trỏ, vì vậy bạn có thể sẽ không đạt được nhiều hơn một danh sách. –

8

Để biết chắc chắn, bạn sẽ phải đo. Dựa trên các hướng dẫn của máy, trình biên dịch có khả năng tạo ra, tôi sẽ thử một mảng, sau đó là một danh sách.

  • Tiếp cận một phần tử mảng đòi hỏi một tấm séc giới hạn, địa chỉ số học, và một tải

  • Tiếp cận người đứng đầu một danh sách đòi hỏi một tải, một thử nghiệm cho danh sách trống, và một tải tại một bù đắp thời gian biên dịch đã biết.

Chi tiết nhanh hơn có thể phụ thuộc vào ứng dụng của bạn và những gì khác đang xảy ra trên máy của bạn. Chúng cũng phụ thuộc vào loại yếu tố; ví dụ, nếu chúng là các số dấu phẩy động, thì ocamlopt có thể đủ thông minh để tạo một mảng không được hộp, điều này sẽ giúp bạn tiết kiệm một mức độ vô hướng.

Các cấu trúc dữ liệu phổ biến khác như bảng băm hoặc cây cân bằng thường yêu cầu bạn phân bổ một số ngữ cảnh ở đâu đó để theo dõi bạn đang ở đâu. Với một mảng, việc theo dõi chỉ yêu cầu một chỉ số nguyên; với một danh sách, việc theo dõi yêu cầu một con trỏ duy nhất. Tôi nghĩ điều này sẽ khó đánh bại trong một cấu trúc dữ liệu khác.

Cuối cùng, xin lưu ý rằng chỉ có thể có một trình biên dịch OCaml, nhưng có hai kết thúc sau: bytecode và mã gốc. Đương nhiên nếu bạn quan tâm đến mức hiệu suất này, bạn đang sử dụng phiên bản ocamlopt gốc. Đúng?

Vui lòng thực hiện các phép đo và chỉnh sửa kết quả vào câu hỏi của bạn.

6

Đừng quên khoảng Bigarray s, chúng gần nhất với mảng C (chỉ là một bộ nhớ bằng phẳng), nhưng không thể chứa giá trị OCaml tùy ý. Cũng xem xét chuyển đổi kiểm tra giới hạn off (unsafe_set/get). Và tất nhiên bạn nên cấu hình trước.

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