2014-04-30 32 views
6

Tôi có một tệp lớn nơi tôi lưu trữ Binary dữ liệu. Có nhiều chủ đề đọc và ghi các tệp này, thiết kế hiện tại của tôi đồng bộ hóa chúng bằng một đơn Lock. Bằng cách này, tôi chỉ có một Handle trong ReadWriteMode mở cho một tệp và tất cả các chuỗi chiến đấu cho khóa đơn đó khi họ cảm thấy thích làm một số I/O.Tệp đồng thời đọc/ghi trong Haskell?

Tôi muốn cải thiện điều này bằng cách cho phép nhiều người đọc làm việc đồng thời. Những gì tôi đã thử đã sử dụng một số RWLock và có nhiều Xử lý mở. RWLock sẽ đảm bảo rằng chỉ có một chủ đề sửa đổi tệp, trong khi nhiều luồng (nhiều như tôi có xử lý mở, hằng số biên dịch) được phép đọc đồng thời. Khi cố gắng chạy điều này, tôi bị ảnh hưởng bởi thực tế là thời gian chạy allows only oneHandle trong ReadWriteMode để tồn tại cho một tệp bất kỳ lúc nào.

Tôi làm cách nào để giải quyết tình huống này? Tôi giả định có được/phát hành Handle là một hoạt động tốn kém, vì vậy chỉ cần mở tệp ở chế độ thích hợp sau khi có được RWLock không thực sự là một tùy chọn. Hoặc có thể có một gói cung cấp một API tương tự như các phương thức readwrite của Java FileChannel?

PS: Tôi muốn hỗ trợ kiến ​​trúc 32 bit, do đó, không thể ánh xạ bộ nhớ IO cho các tệp> 4GiB, phải không?

+0

bạn đã thử sử dụng bất kỳ song song I/O thư viện để đọc ghi tập tin? Có một vài người trong số họ, HDF5, PNetCDF, SIONlib ... tất cả đều hỗ trợ đọc/ghi đồng thời với các tệp song song trong cả hệ thống bộ nhớ được chia sẻ và phân phối và tất cả chúng đều khá tốt với tối đa O (10^4) lõi . – gnzlbg

Trả lời

1

Vì vậy, vấn đề của bạn là bạn không muốn sử dụng trạng thái Handle s (nơi tiểu bang là vị trí hiện tại trong hồ sơ)? Trong trường hợp đó, bạn cần preadpwrite, tôi đoán vậy.

man pread

Đối Haskell ràng buộc: http://hackage.haskell.org/package/unix-bytestring-0.3.7.2/docs/System-Posix-IO-ByteString.html

Đối với một ví dụ sử dụng, bạn có thể xem ở đây: https://github.com/errge/PrefetchFS/blob/master/PrefetchHandle.hs

+0

Điều này giống như một trận đấu hoàn hảo, tôi sẽ thử ngay. – Waldheinz

1

Bạn nên tạo loại xung quanh tay cầm tệp và khóa bằng mutex. Đây là một thực hiện đơn giản mà tôi nghĩ rằng sẽ làm việc cho các mục đích của bạn.

module SharedHandle (SharedHandle, newSharedHandle, withSharedHandle) where 

import Control.Concurrent.MVar 
import System.IO    

data SharedHandle = SharedHandle Handle (MVar()) 

newSharedHandle :: IO Handle -> IO SharedHandle 
newSharedHandle makeHandle = do 
    handle <- makeHandle 
    lock <- newMVar() 
    return $ SharedHandle handle lock 

withSharedHandle :: SharedHandle -> (Handle -> IO a) -> IO a 
withSharedHandle (SharedHandle handle lock) operation = do 
    () <- takeMVar lock 
    val <- operation handle 
    putMVar lock() 
    return val 

Điều gì đang diễn ra ở đây là tôi đã tạo một kiểu dữ liệu mới, chỉ là xử lý tệp. Sự khác biệt duy nhất là nó cũng đi kèm với khóa mutex riêng của nó được thực hiện với một MVar. Tôi đã cung cấp hai chức năng để hoạt động trên loại mới này. newSharedHandle thực hiện một thao tác có thể tạo một handle bình thường và tạo một handle chia sẻ với một khóa mới. withSharedHandle thực hiện một thao tác để vận hành trên các chốt điều khiển, khóa chốt xử lý chia sẻ, thực hiện thao tác và sau đó mở khóa tay cầm. Lưu ý rằng các hàm tạo hoặc các trình truy cập không được cung cấp từ mô-đun để chúng ta có thể yên tâm không có quá trình nào quên sử dụng khóa miễn phí và chúng ta không bao giờ bị deadlocks trên một truy cập cụ thể.

Thay thế tất cả các tay cầm tệp trong chương trình của bạn bằng loại mới này có thể giải quyết được sự cố của bạn.

+0

Đây không phải là những gì tôi đã làm? Tôi không thấy làm thế nào điều này sẽ cho phép nhiều độc giả hoạt động đồng thời, vì tất cả nội dung cho single 'MVar' (ít nhiều được sử dụng như một' Khóa' trong mã này). Ngoài ra, nó không phải là ngoại lệ an toàn.;-) – Waldheinz

+0

Tôi nghĩ bạn muốn có nhiều tệp được ghi cùng một lúc nhưng cá nhân khóa chúng lại để không khóa toàn bộ tập hợp lại với nhau. Nếu bạn muốn thực sự ghi vào cùng một tệp cùng một lúc, không phải là nó chỉ tốt để có điều kiện chủng tộc không được kiểm soát? Posix đã cho phép bạn có nhiều tiến trình nối thêm vào một tệp mà không cần khóa bất kỳ. Tóm lại, vấn đề với chương trình của bạn chỉ là không khóa bất cứ điều gì và để cho quá trình nhanh hơn giành chiến thắng trong cuộc đua và là người đầu tiên viết? – mmachenry

+0

Ồ, có lẽ tôi nên nói rõ ràng: Các tệp của tôi có kích thước cố định và tôi ghi vào/đọc từ các khoảng trống ngẫu nhiên trong một tệp. Vấn đề của tôi là cuộc đua giữa việc tìm kiếm sự bù đắp chính xác và thực sự làm I/O, khi nhiều luồng truy cập vào một tệp duy nhất. Tôi chỉ có hai tập tin, nhưng hàng chục độc giả/nhà văn. – Waldheinz

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