Chiến lược I / O cho các vấn đề tính toán với các tập dữ liệu lớn?


15

Nhóm nghiên cứu của tôi tập trung vào động lực phân tử, rõ ràng có thể tạo ra hàng gigabyte dữ liệu như một phần của một quỹ đạo mà sau đó phải được phân tích.

Một số vấn đề chúng tôi quan tâm liên quan đến mối tương quan trong tập dữ liệu, điều đó có nghĩa là chúng tôi cần theo dõi lượng lớn dữ liệu trong bộ nhớ và phân tích chúng, thay vì sử dụng cách tiếp cận tuần tự hơn.

Điều tôi muốn biết là các chiến lược hiệu quả nhất để xử lý I / O của các tập dữ liệu lớn thành các tập lệnh là gì. Chúng ta thường sử dụng các tập lệnh dựa trên Python vì nó làm cho việc mã hóa tệp I / O ít đau đớn hơn C hoặc Fortran, nhưng khi chúng ta có hàng chục hoặc hàng trăm triệu dòng cần được xử lý, thì không rõ cách tiếp cận tốt nhất là gì . Chúng ta nên xem xét thực hiện phần đầu vào tệp của mã trong C, hay một chiến lược khác hữu ích hơn? (Đơn giản là việc tải trước toàn bộ mảng vào bộ nhớ sẽ tốt hơn một loạt các lần đọc liên tiếp của "khối" (thứ tự của megabyte)?

Một số lưu ý bổ sung:

  • Chúng tôi chủ yếu tìm kiếm các công cụ kịch bản để xử lý hậu kỳ, thay vì các công cụ "trực tuyến" do đó sử dụng Python.

  • D= =16limΔt(x(t+Δt)-x(t))2

Câu trả lời:


6

Tôi cho rằng câu hỏi của bạn xuất phát từ việc quan sát rằng I / O gây ra một chi phí đáng kể trong toàn bộ phân tích của bạn. Trong trường hợp đó, bạn có thể thử chồng chéo I / O với tính toán.

Cách tiếp cận thành công phụ thuộc vào cách bạn truy cập dữ liệu và tính toán bạn thực hiện trên dữ liệu đó. Nếu bạn có thể xác định một mẫu hoặc quyền truy cập vào các vùng khác nhau của dữ liệu đã được biết trước, bạn có thể thử tìm nạp trước "khối tiếp theo" của dữ liệu trong nền trong khi xử lý "khối hiện tại".

Ví dụ đơn giản, nếu bạn chỉ duyệt qua tệp của mình một lần và xử lý từng dòng hoặc tập hợp các dòng, bạn có thể chia luồng theo từng dòng (hoặc MB). Sau đó, tại mỗi lần lặp qua các khối, bạn có thể tải chunk i + 1 trong khi xử lý chunk i.

Tình hình của bạn có thể phức tạp hơn và cần nhiều giải pháp liên quan hơn. Trong mọi trường hợp, ý tưởng là thực hiện I / O trong nền trong khi bộ xử lý có một số dữ liệu để làm việc. Nếu bạn cung cấp thêm chi tiết về vấn đề cụ thể của mình, chúng tôi có thể có thể xem xét sâu hơn về vấn đề đó;)

---- Phiên bản mở rộng sau khi cung cấp thêm chi tiết ----

Tôi không chắc là tôi hiểu ký hiệu, nhưng, như bạn đã nói, ý tưởng là một sự tương tác tất cả. Bạn cũng đề cập rằng dữ liệu có thể phù hợp với RAM. Sau đó, tôi sẽ bắt đầu bằng cách đo thời gian để tải tất cả dữ liệu và thời gian để thực hiện tính toán. Hiện nay,

  • nếu tỷ lệ phần trăm của I / O thấp (thấp như bạn không quan tâm đến chi phí hoạt động, dù đó là gì: 0,5%, 2%, 5%, ...), thì chỉ cần sử dụng phương pháp đơn giản: tải dữ liệu cùng một lúc, và tính toán. Bạn sẽ tiết kiệm thời gian cho các khía cạnh thú vị hơn của nghiên cứu của bạn.

  • nếu bạn không đủ khả năng chi trả, bạn có thể muốn xem xét những gì Pedro đề xuất. Hãy ghi nhớ những gì Aron Ahmadia đã đề cập, và kiểm tra nó trước khi thực hiện đầy đủ.

  • nếu trước đó là không thỏa đáng, tôi sẽ đi cho một số out-of-core thực hiện [1]. Vì có vẻ như bạn đang thực hiện tính toán trên dữ liệu , nên có hy vọng :) Một số mã giả (giả sử kết quả phân tích của bạn phù hợp với RAM):n2n

    tải chunk1 và chunk2
    cho khối i = 1 đến n
        tải không đồng bộ chunk i + 1
        cho các khối trong j = i + 1 đến n
            tải không đồng bộ chunk j + 1
            tính toán với các đoạn i, j (* cho lần lặp đầu tiên, đây là các đoạn được tải sẵn 1 và 2 *)

Lưu ý: đây là mã giả nhanh và bẩn, người ta sẽ cần điều chỉnh các chỉ số.

Để thực hiện điều này, người ta thường sử dụng cái gọi là bộ đệm đôi . Nói một cách đơn giản: phân chia bộ nhớ trong hai không gian làm việc; trong khi dữ liệu đang được tải trong nền vào không gian làm việc 1, bộ xử lý đang tính toán với dữ liệu trong không gian làm việc 2. Tại mỗi lần lặp, trao đổi vai trò.

Tôi xin lỗi tôi không thể đến với một tài liệu tham khảo tốt ngay bây giờ.

[1] Một thuật toán bên ngoài kết hợp một số cơ chế để (xử lý) hiệu quả với dữ liệu cư trú trên đĩa. Chúng được gọi là ngoài lõi so với trong lõi ("trong RAM").


7

Tôi đã phải đối phó với các vấn đề tương tự trước đây và giải pháp yêu thích của tôi là sử dụng I / O được ánh xạ bộ nhớ , mặc dù trong C ...

Nguyên tắc đằng sau nó khá đơn giản: thay vì mở một tệp và đọc từ nó, bạn tải nó trực tiếp vào bộ nhớ và truy cập nó như thể nó là một mảng lớn. Thủ thuật làm cho nó hiệu quả là hệ điều hành không thực sự tải tệp , nó chỉ xử lý nó như bộ nhớ bị tráo đổi cần được tải. Khi bạn truy cập bất kỳ byte đã cho nào trong tệp của mình, trang bộ nhớ cho phần đó của tệp sẽ được hoán đổi vào bộ nhớ. Nếu bạn tiếp tục truy cập các phần khác nhau của tệp và bộ nhớ bị chặt, các phần ít sử dụng sẽ bị tráo đổi - tự động!

Một tìm kiếm nhanh của Google cho tôi biết rằng điều này cũng có sẵn cho Python: 16.7. mmap - Hỗ trợ tệp ánh xạ bộ nhớ , nhưng tôi không biết đủ về Python để biết nó có thực sự giống như vậy không.


1
Chỉ cần chắc chắn rằng bạn đo lường và kiểm tra trước khi thực hiện một cái gì đó giống như mmapvào mã chính của bạn. Nhiều hệ điều hành hiện đại cho hiệu năng tương tự giữa thường xuyên readvới ít biến chứng. (Ngoài ra, có, mmap trong Python cung cấp giao diện di động cho bản đồ bộ nhớ Windows và UNIX).
Aron Ahmadia

1

Có lẽ bạn có thể sử dụng Cython trong phần I / O tệp của bạn và chuyển đổi phần này thành mã 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.