matlab parfor循环中的函数

时间:2014-08-10 19:50:04

标签: matlab parfor matlabpool

你可以在matlab parfor循环中使用函数吗?例如,我有一个看起来像的代码:

matlabpool open 2
Mat=zeros(100,8);
parfor(i=1:100)
    Mat(i,:)=foo();
end

在函数内部我有一堆其他变量。特别是有一段代码如下:

function z=foo()
    err=1;
    a=zeros(10000,1);
    p=1;

    while(err>.0001)

        %statements to update err 
        %   .
        %   .
        %   .

        p=p+1;

        %if out of memory allocate more
        if(p>length(a))
            a=[a;zeros(length(a),1)];
        end
    end

    %trim output after while loop
    if(p<length(a))
        a(p+1:end)=[];
    end

    %example output
    z=1:8;

end    

我在某处读到,必须预先分配嵌套在matlab parfor循环内的for循环内部的所有变量,但在这种情况下,我有一个预先分配的变量,但可能会在以后增长。当我使用mlint时,matlab没有给我任何错误,但我想知道是否有我应该注意的问题。

谢谢,

-Akt

2 个答案:

答案 0 :(得分:4)

根据Mathworks'documentation,您对矩阵Mat的实现是一个切片变量。这意味着您在不同的迭代中更新相同矩阵的不同“切片”,但迭代不会相互影响。循环之间没有数据依赖性。所以你可以去。

a函数foo内的parfor不会影响a,因为foo是位于a堆栈中的常规变量。您可以使用i执行任何操作。

确实存在几个需要注意的问题:

不要将ji用作迭代计数器

在任何目的中定义ja都很糟糕。

我从来没有把人们推荐给这篇文章感到无聊 - Using i and j as variables in Matlab

增长a=[a;zeros(length(a),1)];不好

每次执行% initialize a list of pointers p = 1; cc = 1; c{1} = zeros(1000,1); % use it while (go_on) % do something disp(c{cc}) .... p=p+1; if (p>1000) cc = cc+1; c{cc} = zeros(1000,1); p = 1; end end 时,变量将作为一个整体复制到RAM中的新空位置。由于它的大小每次都翻倍,这可能是一场灾难。不难想象。

更轻松地“成长” -

c

在这里,你会增加一个指针列表,一个单元格数组a。它更小,更快,但仍需要在内存中复制。

使用最少的内存量

假设您只需要a(end-8:end)的一小部分,即Mat(i,:)=foo();作为函数输出。 (此假设基于调用者size(Mat, 2)=8 err。)

假设aa(p-1)的先前元素无关,即a(p-2)a,....(稍后我将放宽此假设。)

您不必将所有以前的结果保留在内存中。如果% if out of memory, don't allocate more; flush it if (p>1000) p = 1; a = zeros(1000,1); end 用完了,就扔掉它。

% if out of memory, flush it, but keep the last 3 results
if (p>1000)
    a = [a(end-3:end); zeros(997,1)];
    p = 4;
end

第二个假设可能会放松,你只需要一定数量的先前元素,而这个数字已经知道(希望它很小)。例如,

% trim output after while loop
a(p+1:end)=[];

修剪并不复杂

>> a=1:10
a =
     1     2     3     4     5     6     7     8     9    10
>> a(3:end)=[]
a =
     1     2
>> a=1:10
a =
     1     2     3     4     5     6     7     8     9    10
>> a(11:end)=[]
a =
     1     2     3     4     5     6     7     8     9    10
>> 

证明:

end

原因是1011:10(虽然你不能将它用作stanalone变量),{{1}}给出一个空数组。

答案 1 :(得分:0)

简短的回答是肯定的,你可以在parfor中调用一个函数。

长期的答案是parfor仅在parfor中的每次迭代独立于其他迭代时才有效。当不是这种情况时,Matlab会检查以捕获;虽然我不知道他们有多全面。在您的示例中,每个foo()调用可以独立运行,并将其返回值存储在Mat的特定位置,该位置不会被任何其他parfor迭代写入或读取,因此它应该可以工作。

如果foo()正在读取Mat中的值,则会发生故障。例如,如果parfor同时运行4次迭代,并且在每次迭代中,foo()从Mat(1)读取然后将新值写入Mat(1),该值基于它读取的内容,读取的时间/ writes会改变输出值,matlab应该标记它。