2009-05-16 3 views
6

Есть ли способ обмена памятью между процессами MATLAB на одном компьютере?Как я могу обмениваться памятью между процессами в MATLAB?

Я запускаю несколько процессов MATLAB на многоядерном компьютере (работает Windows, если это имеет значение). Все они используют одни и те же гигантские входные данные. Было бы неплохо иметь только одну копию в памяти.

Редактировать: К сожалению, для каждого процесса требуется доступ ко всем гигантским входным данным, поэтому нет возможности разделить данные и преодолеть проблему.

+1

Мои данные могут быть большими, но является статическим, т.е. функция не изменяет его. Да. Чтение файла может действительно работать. – AnnaR

ответ

6

Если процессы только когда-либо чтения данных, но не изменяет, то я полагаю, вы можете разместить свои входные данные в один большой файл и имеете каждый процесс открытым и читать из этого файла. Каждый процесс будет иметь свой собственный указатель позиции файла, чтобы он мог перемещаться в любом месте файла, чтобы читать нужные ему данные. Я тестировал, что два процесса MATLAB читают одновременно из файла миллион раз каждый раз, и все, казалось, работает нормально. Я использовал только основные команды ввода-вывода файлов (перечисленные ниже). Похоже, вы также можете сделать это, используя MEMMAPFILE, как указано в его ответе Mr Fooz (и SCFrench в комментарии), если у вас есть версия MATLAB R2008a или новее.

Вот некоторые из файла ввода/вывода команд, которые вы, вероятно, использовать для этого:

  • FOPEN: Каждый процесс будет вызывать FOPEN и возвращает идентификатор файла, которое будет использоваться во всех последующих вызовах. Вы можете открыть файл в любом двоичный или текст режим:

    fid = fopen('data.dat','r'); % Binary mode 
    fid = fopen('data.txt','rt'); % Text mode 
    
  • FREAD: В двоичном режиме, Fread будет считывать данные из файла:

    A = fread(fid,20,'double'); % Reads 20 double-precision values 
    
  • FSCANF: В тексте режиме, FSCANF будет считывать и форматировать данные из файла:

    A = fscanf(fid,'%d',4); % Reads 4 integer values 
    
  • FGETL/FGETS: В текстовом режиме они будут считывать целые строки из файла.

  • FTELL: Это покажет Вам текущий индикатор позиции файла в байтах от начала файла:

    ftell(fid) 
    ans = 
        8 % The position indicator is 8 bytes from the file beginning 
    
  • FSEEK: Это будет установить индикатор позиции файла в нужное положение в файле:

    fseek(fid,0,-1); % Moves the position indicator to the file beginning 
    
  • FCLOSE: Каждый процесс должен будет закрыть доступ к файлу (это легко забыть это сделать):

    fclose(fid); 
    

Это решение, вероятно, потребует, чтобы входной файл имеет хорошо структурированный формат, который легко перемещаться (т.е. только одна большая матрица). Если в нем много полей переменной длины, то чтение данных из правильной позиции в файле может стать очень сложным.


Если процессы должны также изменить данные, это может стать еще более трудным. В общем, вы не хотите, чтобы местоположение файла/памяти было одновременно записано несколькими процессами или записано одним процессом, а другое - с того же места, поскольку может возникнуть нежелательное поведение. В таком случае вам придется ограничить доступ к файлу таким образом, что на нем будет работать только один процесс. Другие процессы должны были ждать, пока не будет сделано первое.Версия образец кода, что каждый процесс должен был бы работать в таком случае:

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 

механизмы синхронизации, подобные этим («locks») иногда может иметь высокую нагрузку, что уменьшает общую параллельную эффективность кода.

+0

Вау! Я попробую это. Это может решить мою проблему. – AnnaR

4

EDIT: Поместите данные в необработанный файл и используйте memmapfile (спасибо SCFrench).

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

Нет, нет реального способа сделать это.

Мои лучшие два решения: купить больше ОЗУ или страницы в данных.

Самое близкое, что вы могли бы сделать, это использовать функцию mex для распределения разделяемой памяти, а затем разрешить последовательные вызовы функции mex для извлечения меньших фрагментов памяти. Вы не хотели бы обертывать общую память как массив Matlab (потому что модель памяти Matlab не справится с этим).

Я собирался предложить изучить memmap, но, видимо, это problematic.

Иногда вы можете сначала запустить одну программу Matlab для предварительной обработки или разделения данных на более мелкие куски. Тогда каждый из процессов Matlab может работать на своем меньшем куске.

Вот tutorial о работе с большими наборами данных в Matlab.

+0

Не тот ответ, который я хотел - я желал «Да, возможно, сделай это». Но большое спасибо за ссылку, я собираюсь ее прочитать прямо сейчас. – AnnaR

+0

Я немного пошутил и, возможно, это делает это: http://polaris.cs.uiuc.edu/matmarks/ –

+1

Я опубликовал обновление для потока новостей comp.soft-sys.matlab, связанного выше с слово «проблематично». Оказывается, это была ошибка в более ранних версиях MATLAB и исправлена ​​с R2008a. – SCFrench

1

Возможно, нет, по крайней мере, не так, как вы обрабатываете данные, как обычная переменная MATLAB.

Если на компьютере с Windows вы можете создать оболочку COM/ActiveX для доступа к вашим общим данным. MATLAB позволяет использовать COM-объекты через функцию actxserver. Но сомнительно, можете ли вы фактически получить доступ к данным «напрямую» с помощью разных процессов. Между MATLAB и COM есть какой-то маршалирующий слой, и данные преобразуются, по крайней мере, согласно документам Mathworks по адресу exchanging data between MATLAB and COM. Если бы я абсолютно имел, чтобы делиться структурированными данными между процессами с быстрым доступом на компьютере под управлением Windows, я бы, вероятно, написал что-то на C++ для использования разделяемой памяти через Boost::interprocess и обернул бы доступ к нему на COM-сервере в процессе (DLL). Я сделал это раньше, один раз. Насколько Boost :: interprocess делает это намного проще, это боль.

Подход Java (поскольку MATLAB работает поверх Java) был бы намного более перспективным, но, насколько я знаю, нет никаких достойных библиотек Java для обеспечения доступа к общей памяти. Самое близкое, вероятно, использовать файл с отображением памяти через java.nio.MappedByteBuffer, но это действительно низкоуровневый. Тем не менее, если ваши данные находятся в относительно «квадратной» форме (например, большая двумерная или трехмерная или четырехмерная матрица с однородными размерами), это может работать нормально.

Вы можете попробовать использовать файлы HDF5, MATLAB имеет встроенный HDF5 support, и это «относительно» быстро. Но по моему опыту, HDF5, похоже, не очень хорошо сочетается с параллелизмом. (по крайней мере, не в том случае, когда один процесс записывается, а другие - читатели. Если есть несколько читателей и нет писателей, он работает отлично.)

5

Возможно, вы захотите проверить мою заявку на обмен файлами Matlab «sharedmatrix» # 28572. Он позволяет матрице Matlab существовать в общей памяти, если вы используете какой-то вкус Unix. то можно было бы прикрепить общую матрицу в теле parfor или SPMD, т.е.

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); 

Поскольку X существует в совместно используемой памяти для тела SPMD (или parfor) не имеет времени нагрузки и нет времени связи , С точки зрения Matlab это новая созданная переменная в теле spmd (или parfor).

Приветствия,

Джош

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

Смежные вопросы