2009-05-16 27 views
6

Có cách nào để chia sẻ bộ nhớ giữa các quá trình MATLAB trên cùng một máy tính không?Làm cách nào để chia sẻ bộ nhớ giữa các quá trình trong MATLAB?

Tôi đang chạy một số quy trình MATLAB trên máy tính đa lõi (chạy Windows, nếu có vấn đề). Tất cả đều sử dụng cùng một dữ liệu đầu vào khổng lồ. Sẽ tốt hơn nếu chỉ có một bản sao của nó trong bộ nhớ.

Chỉnh sửa: Rất tiếc, mỗi quá trình cần truy cập vào toàn bộ dữ liệu đầu vào khổng lồ, do đó không có cách nào để phân chia dữ liệu và khắc phục sự cố.

+1

Dữ liệu của tôi chưa lớn nhưng là tĩnh, nghĩa là chức năng không thay đổi nó. Ừ. Đọc một tập tin thực sự có thể làm việc. – AnnaR

Trả lời

6

Nếu các quá trình duy nhất từng đọc dữ liệu, nhưng không sửa đổi nó, sau đó tôi tin rằng bạn có thể đặt dữ liệu đầu vào của bạn vào một tập tin lớn và có mỗi quá trình mở và đọc từ tập tin đó. Mỗi quá trình sẽ có chỉ báo vị trí tệp riêng của nó mà nó có thể di chuyển bất cứ nơi nào trong tệp để đọc dữ liệu cần thiết. Tôi đã thử nghiệm có hai quá trình MATLAB đọc đồng thời từ một tập tin một triệu lần hoặc mỗi lần và mọi thứ dường như hoạt động tốt. Tôi chỉ sử dụng các lệnh I/O tập tin cơ bản (được liệt kê bên dưới). Nó xuất hiện bạn cũng có thể làm điều này bằng cách sử dụng MEMMAPFILE, như Mr Fooz được đề cập trong câu trả lời của mình (và SCFrench trong một bình luận), giả sử bạn có phiên bản MATLAB R2008a hoặc mới hơn.

Dưới đây là một số các tập tin I/O lệnh mà bạn có thể sẽ sử dụng cho việc này:

  • FOPEN: Mỗi quá trình sẽ gọi fopen và trả về một tập tin định danh nó sẽ sử dụng trong tất cả các cuộc gọi tiếp theo. Bạn có thể mở một tập tin trong cả hai nhị phân hoặc văn bản chế độ:

    fid = fopen('data.dat','r'); % Binary mode 
    fid = fopen('data.txt','rt'); % Text mode 
    
  • FREAD: Trong chế độ nhị phân, fread sẽ đọc dữ liệu từ file:

    A = fread(fid,20,'double'); % Reads 20 double-precision values 
    
  • FSCANF: Trong văn bản chế độ, FSCANF sẽ đọc và định dạng dữ liệu từ tệp:

    A = fscanf(fid,'%d',4); % Reads 4 integer values 
    
  • FGETL/FGETS: Ở chế độ văn bản, chúng sẽ đọc toàn bộ dòng từ tệp.

  • FTELL: Điều này sẽ cho bạn biết chỉ báo vị trí tập tin hiện theo byte từ đầu tập tin:

    ftell(fid) 
    ans = 
        8 % The position indicator is 8 bytes from the file beginning 
    
  • FSEEK: Điều này sẽ thiết lập các chỉ báo vị trí tập tin vào một vị trí mong muốn trong file:

    fseek(fid,0,-1); % Moves the position indicator to the file beginning 
    
  • FCLOSE: Mỗi quá trình sẽ phải đóng truy cập của nó đến tập tin (rất dễ dàng để quên đi để làm điều này):

    fclose(fid); 
    

Giải pháp này có khả năng sẽ yêu cầu các tập tin đầu vào có một định dạng có cấu trúc tốt đó là dễ dàng để đi qua (ví dụ: chỉ một ma trận lớn). Nếu nó có nhiều trường có độ dài thay đổi thì việc đọc dữ liệu từ vị trí chính xác trong tệp có thể rất phức tạp.


Nếu các quá trình phải cũng sửa đổi dữ liệu, điều này có thể nhận được thậm chí khó khăn hơn. Nói chung, bạn không muốn vị trí tệp/bộ nhớ được ghi đồng thời bởi nhiều quy trình hoặc được viết bởi một quy trình trong khi một tệp khác đang đọc từ cùng một vị trí, vì hành vi không mong muốn có thể xảy ra. Trong trường hợp này, bạn sẽ phải hạn chế quyền truy cập vào tệp sao cho chỉ có một tiến trình tại một thời điểm đang hoạt động trên đó. Các quy trình khác sẽ phải đợi cho đến khi quá trình đầu tiên được thực hiện.Một phiên bản mẫu mã mà mỗi tiến trình sẽ phải chạy trong trường hợp này là:

processDone = false; 
while ~processDone, 
    if file_is_free(), % A function to check that other processes are not 
         % accessing the file 
    fid = fopen(fileName,'r+'); % Open the file 
    perform_process(fid);  % The computation this process has to do 
    fclose(fid);     % Close the file 
    processDone = true; 
    end 
end 

cơ chế đồng bộ hóa như thế này ("locks") đôi khi có thể có một chi phí cao làm giảm hiệu quả song song tổng thể của mã.

+0

Wow! Tôi sẽ thử cái này. Điều này có thể giải quyết được vấn đề của tôi. – AnnaR

4

EDIT: Đặt dữ liệu vào tệp thô và sử dụng memmapfile (nhờ SCFrench).

============================================

Không, không có cách thực sự để làm điều đó.

Hai giải pháp hàng đầu của tôi là: mua thêm RAM hoặc trang trong dữ liệu.

Điều gần nhất bạn có thể làm là sử dụng chức năng mex để cấp phát bộ nhớ dùng chung, sau đó cho phép các cuộc gọi liên tiếp đến hàm mex để trích ra các lát nhỏ hơn của bộ nhớ. Bạn sẽ không muốn quấn bộ nhớ chia sẻ thành một mảng Matlab (vì mô hình bộ nhớ của Matlab sẽ không xử lý tốt).

Tôi sẽ đề xuất xem xét bản ghi nhớ, nhưng dường như là problematic.

Đôi khi, trước tiên bạn có thể chạy một chương trình Matlab để xử lý trước hoặc chia nhỏ dữ liệu thành các đoạn nhỏ hơn. Sau đó, mỗi quá trình Matlab có thể hoạt động trên đoạn nhỏ hơn của nó.

Đây là số tutorial về cách xử lý các tập dữ liệu lớn trong Matlab.

+0

Không phải là câu trả lời tôi muốn - tôi đã ước rằng 'Có thể, hãy làm điều này'. Nhưng cảm ơn rất nhiều cho liên kết, tôi sẽ đọc nó ngay bây giờ. – AnnaR

+0

Tôi đã làm nhiều hơn một chút xung quanh và có lẽ điều này hiện nó: http://polaris.cs.uiuc.edu/matmarks/ –

+1

Tôi đã đăng một bản cập nhật cho các chủ đề tin tức comp.soft-sys.matlab liên kết ở trên để từ "có vấn đề". Nó chỉ ra đây là một lỗi trong phiên bản cũ của MATLAB, và được cố định như của R2008a. – SCFrench

1

Có lẽ không, ít nhất là không theo cách bạn xử lý dữ liệu như biến MATLAB thông thường.

Nếu trên máy Windows, bạn có thể tạo trình bao bọc COM/ActiveX để truy cập dữ liệu được chia sẻ của mình. MATLAB cho phép sử dụng các đối tượng COM thông qua hàm actxserver. Nhưng nó là vấn đề cho dù bạn thực sự có thể truy cập dữ liệu "trực tiếp" thông qua các quá trình khác nhau. Có một số loại lớp marshaling giữa MATLAB và COM và dữ liệu được chuyển đổi, ít nhất là theo các tài liệu Mathworks trên exchanging data between MATLAB and COM. Nếu tôi hoàn toàn để chia sẻ dữ liệu có cấu trúc giữa các quy trình, với quyền truy cập nhanh, trên máy Windows, tôi có thể viết gì đó trong C++ để sử dụng bộ nhớ chia sẻ qua Boost::interprocess và truy cập gói vào máy chủ COM trong quá trình (DLL). Tôi đã làm điều này trước đây, một lần. Nhiều như Tăng :: interprocess làm cho nó dễ dàng hơn nhiều, đó là một nỗi đau.

Cách tiếp cận Java (vì MATLAB chạy trên đầu Java) sẽ hứa hẹn hơn nhiều, nhưng theo như tôi biết, không có thư viện Java phong nha nào cung cấp quyền truy cập vào bộ nhớ dùng chung. Điều gần nhất có lẽ là sử dụng tệp ánh xạ bộ nhớ qua java.nio.MappedByteBuffer, nhưng đó thực sự là cấp thấp. Tuy nhiên, nếu dữ liệu của bạn ở dạng tương đối "hình vuông" (ví dụ: ma trận 2-D hoặc 3-D hoặc 4-D lớn có dữ liệu đồng nhất) thì điều này có thể hoạt động OK.

Bạn có thể thử sử dụng các tệp HDF5, MATLAB đã tích hợp sẵn HDF5 support và nó "tương đối" nhanh. Nhưng từ kinh nghiệm của tôi, HDF5 dường như không chơi tốt với đồng thời. (ít nhất là không phải khi một quá trình được viết và những người khác là độc giả. Nếu có nhiều độc giả và không có nhà văn, nó hoạt động tốt.)

5

Bạn có thể muốn thanh toán tập tin trao đổi tập tin Matlab của tôi "sharedmatrix" # 28572. Nó cho phép một ma trận Matlab tồn tại trong bộ nhớ chia sẻ, miễn là bạn đang sử dụng một số hương vị của Unix. Một sau đó có thể đính kèm ma trận được chia sẻ trong một cơ thể của một parfor hoặc spmd, tức là,

shmkey=12345; 
sharedmatrix('clone',shmkey,X); 
clear X; 
spmd(8) 
    X=sharedmatrix('attach',shmkey); 
    % do something with X 
    sharedmatrix('detach',shmkey,X); 
end 
sharedmatrix('free',shmkey); 

Từ X tồn tại trong bộ nhớ chia sẻ cho cơ thể của spmd (hoặc parfor) nó không có thời gian tải và không có thời gian giao tiếp . Từ quan điểm của Matlab nó là một biến mới được tạo ra trong cơ thể spmd (hoặc parfor).

Chúc mừng,

Josh

http://www.mathworks.com/matlabcentral/fileexchange/28572-sharedmatrix

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