向工人发送数据

时间:2015-08-19 12:28:44

标签: matlab parallel-processing parfor spmd

我正在尝试创建一段并行代码,以加快处理非常大(几亿行)的数组。为了与此并行化,我将数据切成8个(我的核心数量)碎片并尝试将每个工人送到1件。然而,看看我的RAM使用情况,似乎每个工件都发送给每个工作人员,有效地将我的RAM使用量乘以8.最小工作示例:

A = 1:16;
for ii = 1:8
    data{ii} = A(2*ii-1:2*ii);
end

现在,当我使用parfor将这些数据发送给工作人员时,它似乎发送了完整的单元格,而不仅仅是所需的单元格:

output = cell(1,8);
parfor ii = 1:8
    output{ii} = data{ii};
end

我实际上在parfor循环中使用了一些函数,但这说明了这种情况。 MATLAB实际上是向每个工作人员发送完整的单元格data,如果是,那么如何使它只发送所需的部分?

3 个答案:

答案 0 :(得分:11)

根据我的个人经验,我发现使用parfeval在内存使用方面优于parfor。此外,您的问题似乎更容易破解,因此您可以使用parfeval向MATLAB工作人员提交更小的工作。

假设您有workerCnt个MATLAB工作人员,您将要处理jobCnt个工作。设data为大小为jobCnt x 1的单元格数组,其每个元素对应于对数据进行分析的函数getOutput的数据输入。然后将结果存储在大小为output的单元格数组jobCnt x 1中。

在以下代码中,作业在第一个for循环中分配,结果在第二个while循环中检索。布尔变量doneJobs表示完成了哪个作业。

poolObj = parpool(workerCnt);
jobCnt = length(data); % number of jobs
output = cell(jobCnt,1);
for jobNo = 1:jobCnt
    future(jobNo) = parfeval(poolObj,@getOutput,...
        nargout('getOutput'),data{jobNo});
end
doneJobs = false(jobCnt,1);
while ~all(doneJobs)
    [idx,result] = fetchnext(future);
    output{idx} = result;
    doneJobs(idx) = true;
end

此外,如果您想节省更多内存,可以更进一步。您可以做的是,在获取完成作业的结果后,您可以删除future的相应成员。原因是该对象存储了getOutput函数的所有输入和输出数据,这可能是巨大的。但是你需要小心,因为删除future的成员会导致索引转移。

以下是我为此porpuse撰写的代码。

poolObj = parpool(workerCnt);
jobCnt = length(data); % number of jobs
output = cell(jobCnt,1);
for jobNo = 1:jobCnt
    future(jobNo) = parfeval(poolObj,@getOutput,...
        nargout('getOutput'),data{jobNo});
end
doneJobs = false(jobCnt,1);
while ~all(doneJobs)
    [idx,result] = fetchnext(future);
    furure(idx) = []; % remove the done future object
    oldIdx = 0;
    % find the index offset and correct index accordingly
    while oldIdx ~= idx
        doneJobsInIdxRange = sum(doneJobs((oldIdx + 1):idx));
        oldIdx = idx
        idx = idx + doneJobsInIdxRange;
    end
    output{idx} = result;
    doneJobs(idx) = true;
end

答案 1 :(得分:5)

@ m.s的注释是正确的 - 当parfor 切片一个数组时,每个工作程序只发送它正在处理的循环迭代所需的切片。但是,您可能会看到RAM使用量的增加超出了您的预期,因为不幸的是,数据的副本是必需的,因为它是通过parfor通信机制从客户端传递给工作人员的。

如果您只需要工作人员的数据,那么最好的解决方案是尽可能在工作人员上创建/加载/访问它。这听起来像是你在数据并行而不是任务并行之后,spmd确实更合适(正如@Kostas建议的那样)。

答案 2 :(得分:3)

我建议使用MATLAB的spmd命令。

您可以编写几乎与非并行实现相同的代码,也可以通过labindex“system”变量访问当前工作程序。

看看这里:

http://www.mathworks.com/help/distcomp/spmd.html

此问题还涉及spmd vs parfor

SPMD vs. Parfor