0

您可以在 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

4

2 回答 2

4

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

a在函数内部增长foo不会影响parfor,因为a它是位于foo堆栈中的常规变量。你可以用a.

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

不要使用iandj作为迭代计数器

定义ij任何目的都是不好的。

我从来没有厌倦过向人们推荐这篇文章——在 Matlab 中使用 i 和 j 作为变量

成长a不好

每次您执行此操作时,都会a=[a;zeros(length(a),1)];将变量作为一个整体复制到 RAM 中的一个新空白位置。由于它的大小每次翻倍,这可能是一场灾难。不难想象。

一种更轻松的“成长”方式——

% 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

在这里,您增长了一个指针列表,一个元胞数组c。它更小、更快,但仍然需要在内存中复制。

使用最少的内存

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

Supposeerr与 的先前元素无关a,即 , a(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
>> 

原因是end10尽管您不能将其用作独立变量),并11:10给出一个空数组。

于 2014-08-10T20:11:57.577 回答
0

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

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

如果 foo() 正在读取 Mat 中的值,则会出现这种情况。例如,如果 parfor 同时运行 4 次迭代,并且在每次迭代中, foo() 正在从 Mat(1) 读取,然后根据读取的内容向 Mat(1) 写入一个新值,读取的时间/writes 会改变输出值,matlab 应该标记它。

于 2014-08-10T20:17:29.813 回答