MATLAB中的信号量和锁定

时间:2011-06-20 17:49:47

标签: matlab semaphore race-condition

我正在开发一个MATLAB项目,我想让两个MATLAB实例并行运行并共享数据。我将调用这些实例MAT_1MAT_2。更具体地说,系统的架构是:

  1. MAT_1按顺序处理图像,使用imread逐个读取图像,然后使用imwrite输出每个图像的结果。
  2. MAT_2使用MAT_1读取imread输出的图片,并将结果输出到其他地方。
  3. 我认为我需要解决的一个问题是保证MAT_2MAT_1完全写入后MAT_1读取MAT_1的图像输出。

    我的问题是:

    1. 你会如何解决这个问题?我是否需要使用信号量或锁来防止竞争条件?
    2. MATLAB是否提供锁定文件的任何机制? (即类似flock的东西,但由MATLAB直接提供,并且可在多个平台上运行,例如Windows和Linux)。如果没有,您是否知道我可以使用任何第三方库在MATLAB中构建此机制?
    3. 编辑:

      • 正如@yoda指出的那样,并行计算工具箱(PCT)允许阻止MATLAB工作者之间的调用,这很棒。也就是说,我对不需要PCT的解决方案特别感兴趣。
      • 为什么我要求MAT_2MAT_2以并行线程运行?:

        MAT_1中的处理平均速度较慢(并且更容易崩溃),而MAT_1的输出会提供其他程序和流程(包括人工检查)不需要等待MAT_2完成其工作。

      答案:

      • 对于允许实施信号量但不依赖PCT的解决方案,请参阅下面的Jonas答案
      • 有关问题的其他好方法,请参阅下面的Yoda答案

6 个答案:

答案 0 :(得分:7)

我会使用信号量来接近这个;根据我的经验,PCT同步速度过慢。

dfacto(另一个答案)为MATLAB提供了很好的信号量实现,但它不适用于MS Windows;我改进了这项工作,以便这样做。改进后的工作如下:http://www.mathworks.com/matlabcentral/fileexchange/45504-semaphoreposixandwindows

这比与Java,.NET,PCT或文件锁接口相比,性能更好。这不使用并行计算工具箱(PCT),并且AFAIK信号量功能无论如何都不在PCT中(令人费解的是他们将其排除在外!)。可以使用PCT进行同步,但我在其中尝试的所有内容都非常慢。

要将这个高性能信号量库安装到MATLAB中,请在MATLAB解释器中运行: mex -O -v semaphore.c

您需要安装C ++编译器才能将semaphore.c编译为二进制MEX文件。然后可以从MATLAB代码中调用该MEX文件,如下例所示。

用法示例:

function Example()
    semkey=1234;
    semaphore('create',semkey,1);
    funList = {@fun,@fun,@fun};
    parfor i=1:length(funList)
        funList{i}(semkey);
    end
end
function fun(semkey)
    semaphore('wait',semkey)
    disp('hey');
    semaphore('post',semkey)
end

答案 1 :(得分:4)

就个人而言,我会使用并行处理工具箱。

据我所知,在Matlab中没有直接的方法来获得系统范围的文件锁。但是,为了确保Matlab#2仅在文件写完时读取Matlab#1的输出,我建议在写完文件results_1.mat后,Matlab#1写入第二个文件{{1} },这是一个空文本文件。由于第二个文件是在第一个文件之后写入的,因此它的存在表示结果文件已被写入。因此,您可以搜索扩展名为results_1.finished的文件,即finished,并使用dir('*.finished')获取您要使用Matlab#2加载的.mat文件的名称。

答案 2 :(得分:2)

我不确定您是否在寻找仅限matlab的解决方案,但我刚刚提交了一个用于Matlab的信号量包装器。它作为通用信号量工作,但它的设计主要考虑了sharedmatrix

Mathworks接受提交后,我将更新我的研究组blog上的链接。

请注意,此mex文件是POSIX信号量功能的包装器。因此,它可以在Linux,Unix,MacOS中运行,但不会在Windows上开箱即用。它可以在针对cygwin库编译时起作用。

答案 3 :(得分:1)

我认为除了使用特定于操作系统的锁之外,还有一种万无一失的方式。一种方法可能是让MAT_1做:

imwrite(fileName);
movefile(fileName, completedFileName);

让MAT_2只处理completedFileName。

答案 4 :(得分:1)

编辑:

看到您的编辑后,一个不涉及使用任何工具箱的简单解决方案如下:

由于MAT_2MAT_1慢得多,因此请延迟MAT_2。即,在MAT_1完成处理后开始说5张图像左右。如果您执行此操作,MAT_2将永远不会遇到MAT_1,因此永远不会处于必须“等待”来自MAT_1的图片的情况。


我仍然不清楚你问题中的一些事情:

  1. 你说MAT_1按顺序处理图像,但是否必须?换句话说,它们的处理顺序是否重要?
  2. 您说MAT_2读取MAT_1的输出...是否必须按照MAT_1完成的顺序或可以是任何顺序?
  3. 您说MAT_2使用imread读取图像并将其输出到其他位置。是否有任何理由无法将任务合并到MAT_1中?
  4. 在任何情况下,您都可以使用并行计算工具箱实现某种形式的执行阻止;但不是使用parfor循环(这是大多数人使用的循环),而是必须创建分布式作业(example)。

    需要注意的重要一点是,每个工作人员(实验室)都有labindex,您可以使用labSend将数据从工作人员1(相当于MAT_1)发送给工作人员2 (相当于MAT_2),然后使用labReceive接收它。来自labReceive的文档:

      

    此功能会阻止实验室中的执行,直到发送实验室中发生相应的labSend调用。

    这就是您想要对MAT_1MAT_2进行的操作。

    另一种方法是在当前会话中生成一个额外的worker,但只将MAT_1执行的任务分配给它。然后,您为任务设置FinishedFcn属性以执行MAT_2执行的功能集,但我不推荐它,因为我不认为这是FinishedFcn的意图,我不知道在某些情况下它是否会破裂。

答案 5 :(得分:0)

我还建议您查看并行处理工具箱中的内容,您希望的功能应该放在某处。我认为这比尝试同步两个MATLAB实例更简洁(除非你被迫使用两个实例)。

在奇怪的情况下,没有这样的东西,你也可以看看不同的环境来实现你想要的东西。这可能是一种解决方法,但您始终可以将MATLAB代码与其他语言(例如Java,.NET,C,...)连接,并使用您习惯使用的功能。使用Java,您可以确信您的解决方案是独立于平台的,.NET仅适用于Windows(至少与MATLAB结合使用)。