班级的示例代码:
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
?
parfor
与静态方法,parfor
与非静态方法进行比较,并使用arrayfun
进行串行执行。
测试用例1:parfor
使用非静态方法(控制)
从内存使用记录中可以看出,单个对象testcls
的创建使用~700MB RAM,由标签1
表示,后面跟着一个clear
命令作为2
,parfor
循环在标签3
上方运行。 parfor
的峰值使用率大约是单个对象的4倍,而池有4个工作者。
测试用例2:parfor
使用静态方法
完成测试程序并以相同方式标记。根据这一证据,结论是只使方法静态不会阻止parpool为所有工人产生相同的对象。
测试案例3:使用arrayfun
由于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
进行序列验证。
答案 0 :(得分:1)
对于不必引用类的任何属性的方法,最好使它们static methods。来自文档:
静态方法与类关联,但与该类的特定实例无关。与操作类的特定对象的普通方法不同,这些方法不需要类的对象作为输入参数。您可以在不创建类
的对象的情况下调用静态方法
由于可以在不必创建该类对象的情况下调用它们,因此这可以帮助您避免每个工作程序中不必要的重复整个对象。
示例方法:
classdef testcls
...
methods(Static)
function sayhello
disp('Hello!');
end
end
...
end
并从每个工人那里打电话:
testcls.sayhello();