参考parfor循环中的类方法:大量内存使用

时间:2017-07-11 18:10:27

标签: matlab parfor

班级的示例代码:

classdef testcls
    methods
        function sayhello(~)
            disp('Hello! ')
        end
    end 
end

现在,如果我在parfor中调用方法,如下所示

A = testcls;
parfor ii = 1:4
    A.sayhello()
end

Mlint告诉我在循环中使用A的性能问题:

  

整个数组或结构'obj'是广播变量。这可能会导致不必要的通信开销。

我可以使用匿名函数来抑制此消息:

A = testcls;
f = @A.sayhello;
parfor ii = 1:4
    f()
end

但我的问题是,无论如何,这对速度有帮助吗?有没有更好的方法来调用parfor中的方法?

那么,如果我想设置函数的输入/输出参数,情况会变得更复杂吗?

classdef testcls
    methods
        function [out1,out2] = sayhello(~,n)
            out1 = (['Hello! ', num2str(n)]);
            out2 = n;
        end
    end
end

A = testcls;
f = @A.sayhello;
[a,b] = deal(cell(4,1));
parfor ii = 1:4
    [a{ii},b{ii}] = feval(f,ii);
end

编辑:

我观察到与内存复制操作相关的大量资源消耗。基本上,作业调度程序将为每个工作程序创建一个相同的对象,包括所有已修改的属性。

f = @A.sayhello;用法并不能保存Matlab将整个对象记忆到每个单独的工作者,即使方法本身没有调用或存储任何类属性。

我认为这是确保透明度的方法。然而,当数据量巨大时,这将成为一个巨大的痛苦。

有没有办法,而不是将所需的功能隔离到一个独立的基于文件的函数中,而是在不会调用整个对象的memcopying的对象中打包sayhello

编辑:感谢@gnovice的暗示性答案。我已经做了一个测试用例,以便将parfor与静态方法,parfor与非静态方法进行比较,并使用arrayfun进行串行执行。

测试用例1:parfor使用非静态方法(控制)

parfor non-static

从内存使用记录中可以看出,单个对象testcls的创建使用~700MB RAM,由标签1表示,后面跟着一个clear命令作为2parfor循环在标签3上方运行。 parfor的峰值使用率大约是单个对象的4倍,而池有4个工作者。

测试用例2:parfor使用静态方法

parfor static

完成测试程序并以相同方式标记。根据这一证据,结论是只使方法静态不会阻止parpool为所有工人产生相同的对象。

测试案例3:使用arrayfun

进行系列评估

serial

由于arrayfun执行非顺序串行批处理评估,因此arrayfun没有理由使用比单个线程所需更多的内存。因此证据。

示例代码:

classdef testcls
    properties
        D
    end
    methods (Static = false)
        function [out1,out2] = sayhello(~,n)
            out1 = (['Hello! ', num2str(n)]);
            out2 = n;
        end
    end
    methods
        function obj = testcls(~)
            obj.D = rand(1e8,1);
        end
    end
end

要运行测试,请使用以下脚本:

clear;clc;close all

A = testcls;
f = @A.sayhello;
parfor ii = 1:4
    feval(f,ii)
end

您可以将parfor替换为arrayfun进行序列验证。

1 个答案:

答案 0 :(得分:1)

对于不必引用类的任何属性的方法,最好使它们static methods。来自文档:

  

静态方法与类关联,但与该类的特定实例无关。与操作类的特定对象的普通方法不同,这些方法不需要类的对象作为输入参数。您可以在不创建类

的对象的情况下调用静态方法

由于可以在不必创建该类对象的情况下调用它们,因此这可以帮助您避免每个工作程序中不必要的重复整个对象。

示例方法:

classdef testcls
  ...
  methods(Static)
    function sayhello
      disp('Hello!');
    end
  end
  ...
end

并从每个工人那里打电话:

testcls.sayhello();