编辑注意:此文件被选为Matlab Central本周精选
注意,自从MATLAB发布R2015b, parallel.pool.Constant取代
WorkerObjWrapper。
WorkerObjWrapper是为以下情况设计的
PARFOR循环体中多次需要数据
一个SPMD块,而这段数据对于
创建,不需要重新创建多个
次了。例子可能包括:数据库连接句柄,大
数组,等等。
考虑这样一种情况,每个工人都需要访问一个大型
而是常数组的数据。而这个数据集可以传递到
在PARFOR块的主体中,它不会持久化,也会持久化
被转移到每个栏杆的每个工人。例如:
largeData = generateLargeData(5000);
Parfor ii = 1:20
x(ii) = someFcn(largeData);
结束
Parfor ii = 1:20
y(ii) = someFcn(largeData, x(ii));
结束
这可以简化成这样:
wrapper = WorkerObjWrapper(@generateLargeData, 5000);
Parfor ii = 1:20
x(ii) = someFcn(wrapper。值);
结束
Parfor ii = 1:20
y(ii) = someFcn(wrapper。价值,x (ii));
结束
在这种情况下,函数“generateLargeData”只被计算
每位工作人员一次,没有大数据转移
客户到工人。大数据从工人清除
当变量“包装器”超出范围或被清除时
客户端。
另一个例子可能是构造特定于工作人员的
日志文件。可以这样实现:
%构建一个函数句柄来打开一个有编号的文本文件:
FCN = @() fopen(sprintf('worker_%d.txt', labindex), 'wt');
%打开每个worker的文件句柄,指定fclose
%将在稍后用来“清理”创建的文件句柄。
w = workerobjwrapper(fcn,{},@fclose);
%运行parfor循环,记录到哪个worker操作哪个磁盘
%循环迭代
parfor ii = 1:10
fprintf(w.Value, '%d\n', ii);
结束
清楚w;%导致在工人上调用“fclose(w.Value)”
键入worker_1.txt %查看哪个worker 1得到了迭代
MathWorks并行计算工具箱团队(2021)。工人对象包装器(//www.tatmou.com/matlabcentral/fileexchange/31972-worker-object-wrapper), MATLAB中央文件交换。检索。
我试图用parcol调用两个java对象。并且我将Java对象类似于下面的路线。但是我出错了:“没有适当的方法,属性或”ClussBjWrapper“的”值“。”你能帮我解决这个问题吗?非常感谢!!
dath ='thorup.jar';
javaaddpath (dpath);
Aspl = 0 (num_v, num_v);%all最短路径长度
np = de.unikiel.npr.thorup.util.ThorupTest.maincode;
wrapperobj_np = workerobjwrapper(np);
thorup = np.construct (competition_graph_edges。”,num_v);
wrapperObj_thorup = WorkerObjWrapper (thorup);
Parcon i = 1:num_v
%计算从原点i-1到所有其他节点的最短路径长度
np_main = wrapperObj_np.value;
%导入thorup算法
% thorup = np_main.construct (competition_graph_edges。”,num_v);
aspl(我)= np_main.calculate(张、wrapperObj_thorup num_v);
结束
嗨xialei - 是,单元格数组或结构将适用于此。
嗨,伙计们,谢谢你们分享这个很棒的想法。我想知道如果我想在我的工作空间中包装一些不同大小和尺寸的数组,我应该做什么。我应该首先将它们分组到单元格或结构?
伟大的
Hi Maximilian——这是预期的,每个工人都得到该值的完整副本。包装器只是帮助您在工作者上构建价值,并避免多次构建或复制它。
如果我使用包装器,并运行以下代码:
Y = RAND(10000,10000)
x = workerobjwrapper(y)
但运行第二个命令后的内存使用量大约高numCPU
嗨Stefano,
嗯,我不确定问题出在哪里。如果你有代码重现这个问题,你可以把它贴在MATLAB Answers上…
干杯,Edric。
非常感谢edric,
我不认为这是我的情况,因为我只在客户端上打开一次并行池,检查它是否已经运行:
启动并行池
p = gcp(“nocreate”);%如果没有池,不要创建新的池。
如果是谬误(p)
P = parpool('local', 1);
其他的
poolsize = p.numworkers;%获取num工人
结束
你有其他建议吗?
嗨Stefano,
如果你关闭并重新打开并行池,你可以碰到这个错误,例如:
Pool = parpool('local', 1);
w = WorkerObjWrapper (7);
删除(池);
Pool = parpool('local', 1);
spmd, disp (w.Value)结束
这可能是你的原因吗?
我试图使用perfeval的WorkerObjWrapper,但是,尽管(我认为)正确地创建了WorkerObjWrapper,
[…]extract from main.m
%准备Java对象包装器
wrapArgs = {wpath, fName, numFolds};
wrapperobj = workerobjwrapper(@generyobj,wrapargs);
[…]
把整个物体送到工人,
[…]extract from main.m
并行化运行
为f = 1: N
%调用并行函数计算
结果(f)= parfeval(p,@parfunc,2,wath,wrapperobj,n,f);
结束
%收集结果
为f = 1: N
[completedTask、价值]= fetchNext(结果);
fprintf('Got result #%d\n', completedTask);
结束
[…]
挑选出来的.value提起(即包裹函数的输出,在我的情况下,在我的情况下)在客户端上并在客户端上称为Parfeval,
[…]extract from parFunc.m
wrapObj = wrapperObj.Value;
数据= wrapObj.data;
兰德= wrapObj.rand;
关系= wrapObj.relation;
[…]
我收到错误:
主机错误(第90行)
[completedTask、价值]= fetchNext(结果);
引起的:
错误使用WorkerObjWrapper /。值(109行)
断言失败。
请问有没有人知道这个错误的可能原因?
非常感谢提前为这个空间,任何帮助和您的时间
干杯
使用R2015A时,我没有看到问题。您使用的是什么操作系统以及群集类型?你总是看到这个,还是有时候?
我广泛地使用了旧的matlab版本的包装器,没有任何问题。
在2015a我得到一个问题,需要重新启动一个新的matlab会话:
使用Wellerobjwrapper>(SPMD)(第155行)错误
安装SPMD执行期间发生错误。如果这个问题
如果持久化,则可能需要删除并再次启动并行池
使用parpool。
Wellerobjwrapper / workerinit时出错(第155行)
spmd, WorkerObjWrapper;第一次结束工作
访问问题
WorkerObjWrapper错误(第97行)
WorkerObjWrapper。workerInit(tmpId, ctor, args, dtor);
并行错误_due_mat_script_with_restart_1(第130行)
wrapper=WorkerObjWrapper(Sys),% share Sys to workers
我有一个问题。我想在parfor循环中使用一个单元格变量,并通过mex文件调用C代码。它显示一个错误!!!!我知道Worker Object Wrapper输出的类型已经是cell,所以mex文件不能工作!!有没有简单的方法来解决这个问题!!
@Hugo这个错误意味着你的并行池基本上崩溃了。如果你简单地尝试会发生什么
SPMD.
disp(尺寸(trackmat));
结束
?
嗨,我使用matlab r2014a运行此代码以下错误:
> > w = WorkerObjWrapper (trackMat);
使用WorkerObjWrapper>(spmd)出错(第156行)
SPMD正在使用的并行池已经关闭。
WorkerObjWrapper/workerInit出错(第156行)
SPMD.
WorkerObjWrapper错误(第97行)
WorkerObjWrapper。workerInit(tmpId, ctor, args, dtor);
客户端与worker 4失去连接。这可能是由于网络
问题,或者交互式沟通工作可能出错。
trackMat是一个由single和w=WorkerObjWrapper(magic(5))组成的大型矩阵,工作得很好。
什么好主意吗?
trackMat是一个由single和w=WorkerObjWrapper(magic(5))组成的大型矩阵,工作得很好。
伟大的文件!这大大提高了我的代码速度。
@Dan,试着用下面的代码替换第136行:
地图= containers.map(uint32(0),[],'统一值',false);
这是R2009a语法。
@Edric -嗨。谢谢你这么快的回复!我运行一个相当老的版本的MATLAB, MATLAB 7.8.0 (R2009a)。
当我跑步时:
> >容器。Map('KeyType', 'uint32', 'ValueType', 'any')
我以前得到了同样的错误:
???找不到具有匹配签名的构造函数'containers.map'。
谢谢!
@Dan——这个错误绝对是意料之外的。你用的是哪个版本的MATLAB/PCT ?如果你尝试执行会发生什么
容器。Map('KeyType', 'uint32', 'ValueType', 'any');
在MATLAB ?
运行示例代码时,我会收到以下错误
w = WorkerObjWrapper(magic(5));
???找不到具有匹配签名的构造函数'containers.map'。
如何修正错误?
谢谢
丹
工作得很好,谢谢!
不过,它确实消耗了相当多的内存。由于“随机访问常量数据”似乎是许多数据密集型应用程序的最常见模型,如果Matlab将来能以某种方式支持跨实验室的只读共享内存,那就太好了。金宝app
完美地为SQL JDBC连接工作。谢谢你的帮助,Edric。
w = workerobjwrapper(@connjdbc,{'dbname','servername'},@close);
conn = connJDBC(databasename, servername)
s.DataReturnFormat =“数据集”;
s.NullNumberRead =“NaN”;
s.NullNumberWrite =“NaN”;
s.NullStringRead =“零”;
s.NullStringWrite =“零”;
setdbprefs
康涅狄格州=数据库(数据库名,”、“‘com.microsoft.sqlserver.jdbc.SQLServerDriver’,……
['jdbc:sqlserver:// servername ';database=' databasename ';integratedSecurity=true;']);
嗨马特,供你参考-我更新的版本在这里包括那个修复。干杯,Edric。
嗨Edric,
似乎工作了!谢谢。
嗨Matt,没有必要地致电SPMD内部 - 这不是问题。由于复合材料的工作方式,当他们超出范围时,工人不会立即发现,只有下一个SPMD块。如果将SPMD块添加到函数,这是不够的,因为在CompractoBjWrapper删除期间创建复合时会发生。
下一个建议:尝试添加以下行
val = [];井底扭矩= [];valdtor = [];
作为workerDelete中SPMD块的最后一行。
我的意思是说,它是一个_peculiar_向空SPMD块中的工人发送命令应该具有这种效果。
嗨Edric。一个空的spmd块会清除它们,但只能从命令行清除。把它放在创建包装器对象的函数的末尾没有什么好处。我还尝试在您推荐的地方的classdef中插入一个空的spmd块。这也没有影响任何东西。
空SPMD块是否要清除对象是希望的?特别是向工人发送没有命令才能清晰。启用它不会更好
spmd,清楚obj;结束
为什么不是SPMD.
嗨Matt,随着您的最新再现放入功能内,我看到工人在函数返回后抓住内存,但空的“SPMD,结束”块足以清除它们。你没有看到这种行为吗?
请注意,构成要保留的内存的复合材料是在WellerBjwrapper中创建的复合材料,而不是您的代码。
嗨Edric,
不,甚至做
SPMD,清除W,结束
不释放内存。此外,当SPMD没有全部使用时(即没有复合材料),我的测试修改中也存在问题。
[N、R、C] =交易(300380480);
S = sprand (C、N ^ 2, 4 / N);
w = WorkerObjWrapper(@(a,b)零(a,b), {N^2,R});
抽搐;
parfor i =一60
y {} = S * w.Value;
结束
toc;
嗨,马特,
我看到了同样的事情。问题是Composite值的内存没有被清除。下一个“spmd”块将修复问题,或者您可以尝试在第120行调用workerDelete之后添加一行“spmd, end”。
干杯,Edric。
我不知道这是否是一个平台依赖的东西,但在下面的代码中,我没有看到w分配的内存值清除时,从工作者w超出范围。
功能测试
[N、R、C] =交易(300380480);
S = sprand (C、N ^ 2, 4 / N);
w = WorkerObjWrapper(@(a,b)零(a,b)+labindex, {N^2,R});
SPMD.
w.Value;
结束
抽搐;
parfor i =一60
y {} = S * w.Value;
结束
toc;
结束
运行上面的代码后,任务管理器显示了大约3GB的内存使用情况。这是在
戴尔精密T7500
Intel Xeon X5680 3.33Ghz
双重hexacore
你好乔,有一个错误在WorkerObjWrapper,我将提交一个修复-但在此期间,你可以尝试运行
spmd, WorkerObjWrapper;结束
在做任何其他事情之前,这应该为你解决问题。
伟大的文件!在我编写的模拟中,它将parfor循环的速度提高了30%。
一个问题:我第一次在我的程序中运行这个,我得到以下错误:
使用WorkerObjWrapper>(spmd body)出错(第161行)
你不能获得'WorkerObjWrapper'的'Map'属性。
你不能获得'WorkerObjWrapper'的'Map'属性。
对于我拥有的每个worker,这个错误都会发生一次,并终止我的脚本。当我再次运行我的脚本(没有更改)时,WorkerObjWrapper工作得很好,没有错误发生。我称它为(简化)形式:
tsteps = 1:1;
xpoints = 1:10 0;
对于jj = tsteps
在这里省略其内容,其产生大矩阵的KK = 6种不同量(“BigMatrix(II,KK)”),其在时间演变,并且需要检查每个X点处的每个时间步骤。
bigMatrixWrapped = WorkerObjWrapper (bigMatrix);
Parfor ii = xpoints
bigmatrixw = bigmatrixwrapped.value;
结果(ii, jj) = processResults (bigMatrixW (ii));
结束
结束
......
错误发生在“bigMatrixWrapped = WorkerObjWrapper(bigMatrix);”这一行,所以我甚至不确定我的parfor循环的结构是否重要,除非出于某种原因,WorkerObjWrapper不喜欢被重复调用。但是,然后再次运行整个脚本,没有“Map”错误(我甚至不确定这是什么意思),并且在“results(ii,jj)”矩阵中收集了预期的结果。
什么好主意吗?
谢谢你的好文件!
然而,我试图以以下方式在代码中使用它,与非并行化版本的代码相比,它导致了模拟运行时间的增加。
我正在处理大型数组和数据文件,必须为非常多的不同情况计算一些统计数据。
在我的代码的初始非并行化版本中,我在for循环中计算了情况1到情况10^7的统计数据。
非并行化代码:
...“读过很多文件”
...“生成大数组”
对于i:1 = 10 ^ 7
...“计算的统计”
结束
...将统计数据写入文本文件
在代码的并行化版本中,我使用Parcom循环。但是,由于MATLAB限制和错误,我不能拥有所有代码直接在PAR循环中直接计算统计信息。因此,我必须创建一个名为stat的新功能,并复制所有代码以计算此功能中的统计信息。
并行代码:
...“读过很多文件”
...“生成大数组”
w1 = workerobjwrapper(sally_array1);
w2 = WorkerObjWrapper (Large_Array2);
w3 = workerobjwrapper(sally_array3);
parfor我:1 = 10 ^ 7
STAT (w1。价值,w2。价值,w3。值,arg1, arg2, arg3, arg4);
......“slice stat”
结束
...将统计数据写入文本文件
我的并行版本的问题是它比非并行版本花费的时间长得多。在PARFOR循环中,我必须调用一个函数(STAT)并在每次迭代中传递许多大型数组(w1.Value)。
有人知道优化/并行化这段代码的最佳方法吗?
很多谢谢!
说得对,塞巴斯蒂安。我唯一的想法是,不知怎的,SPMD设法通过共分布数组使这种事情成为可能,所以我想知道为什么PARFOR不能。
也许我错了,但我会尽量解释得更好。通常在parfor循环中调用多次,我有两种数据类型。一个是不断变化的,一个是固定在parfor循环上的。
例如:
A = rand (x2, 1);
B = rand (x2, 1);
对于i1 = 1:x1
Parfor i2 = 1: x2
A = fun1 (A (i2), b (i2));
结束
A = fun2 (A, b);
结束
有趣的是,切片变量“b”是持久的,而切片变量“a”会自动通过parfor驱动。
现在可以确定,存储在每个工作器中的b的剩余部分对应于在每次parfor循环调用中从“a”发送给工作器的部分?
这就是我的问题。
对不起我的英语。
嗨,塞巴斯蒂安,
不确定你的意思是“以不同方式分发了数据在每个议定书中分发了数据”或如何与我的评论相关。我要求通过调用拨打的数据切片持续的数据。这意味着数据将在每个Parcol中以相同的方式分发,而不是不同的方式。
嗨,马特·J。
好主意,但我认为很难在parfor循环中,如果它在每个parfor调用中以不同的方式分发数据。据我所知,在parfor中并没有定义每个工作者接收什么信息。
嗨Edric,
看起来非常有用,但是您的示例展示了如何在2个后续的PAR环上持续到持续的数据似乎仅限于未拟合的数据。我想知道该课程是否会允许切片数据持续存在(不需要被重绘)。