如何在MATLAB中的进程之间共享内存?

时间:2009-05-16 11:13:09

标签: matlab memory process parallel-processing

有没有办法在同一台计算机上的MATLAB进程之间共享内存?

我在多核计算机上运行几个MATLAB进程(运行Windows,如果重要的话)。它们都使用相同的巨大输入数据。在内存中只有一个副本就好了。

编辑:不幸的是,每个进程都需要访问整个巨大的输入数据,因此无法分割数据并解决问题。

4 个答案:

答案 0 :(得分:6)

如果流程只是读取数据,但不修改,那么我相信您可以将输入数据放入一个大文件中并让每个流程都打开并从该文件中读取。每个进程都有自己的文件位置指示器,它可以移动到文件中的任何位置以读取所需的数据。我测试了两个MATLAB进程同时从文件中读取了一百万次左右,一切似乎都运行正常。我只使用了基本的文件I / O命令(如下所列)。您似乎也可以使用MEMMAPFILE执行此操作,如他的回答中提到的Mr Fooz(以及注释中的SCFrench),假设您有MATLAB版本R2008a或更新版本。

以下是您可能会使用的一些文件I / O命令:

  • 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”)有时会产生很高的开销,从而降低了代码的整体并行效率。

答案 1 :(得分: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

答案 2 :(得分:4)

编辑:将数据放入原始文件中并使用memmapfile(感谢SCFrench)。

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

不,没有真正的方法可以做到这一点。

我的前两个解决方案是:在数据中购买更多RAM或页面。

你可以做的最接近的事情是使用mex函数来分配共享内存,然后允许连续调用mex函数来提取较小的内存片。你不希望将共享内存包装为Matlab数组(因为Matlab的内存模型不能很好地处理它)。

我打算建议查看memmap,但显然是problematic

有时你可以先运行一个Matlab程序来预处理或将数据拆分成更小的块。然后,每个Matlab进程都可以在自己的较小块上运行。

这是关于在Matlab中处理大型数据集的tutorial

答案 3 :(得分:1)

可能不是,至少不像处理常规MATLAB变量那样处理数据。

如果在Windows计算机上,您可以创建COM / ActiveX包装器来访问共享数据。 MATLAB允许通过actxserver函数使用COM对象。但是,您是否可以通过不同的流程“直接”访问数据是值得怀疑的。 MATLAB和COM之间存在某种编组层,并且数据被转换,至少根据exchanging data between MATLAB and COM上的Mathworks文档。如果我绝对 在进程之间共享结构化数据,快速访问,在Windows机器上,我可能会用C ++编写一些内容来通过Boost::interprocess使用共享内存并封装对它的访问权限在进程内COM服务器(DLL)中。我曾经这样做过一次。就像Boost :: interprocess一样,它变得更容易,这很痛苦。

Java方法(因为MATLAB在Java之上运行)会更有希望,但据我所知,没有任何体面的Java库可以提供对共享内存的访问。最接近的可能是通过java.nio.MappedByteBuffer使用内存映射文件,但这确实是低级别的。尽管如此,如果您的数据采用相对“正方形”的形式(例如,大小均匀数据的2-D或3-D或4-D矩阵),这可能正常。

您可以尝试使用HDF5文件,MATLAB内置HDF5 support并且它“相对”快。但根据我的经验,HDF5似乎并不能很好地兼顾并发性。 (至少不是在一个过程正在写作而其他过程是读者的时候。如果有多个读者而没有作者,那就可以了。)