你可以在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
答案 0 :(得分:4)
根据Mathworks'documentation,您对矩阵Mat
的实现是一个切片变量。这意味着您在不同的迭代中更新相同矩阵的不同“切片”,但迭代不会相互影响。循环之间没有数据依赖性。所以你可以去。
a
函数foo
内的parfor
不会影响a
,因为foo
是位于a
堆栈中的常规变量。您可以使用i
执行任何操作。
确实存在几个需要注意的问题:
j
和i
用作迭代计数器在任何目的中定义j
或a
都很糟糕。
我从来没有把人们推荐给这篇文章感到无聊 - 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
。)
假设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
>>
证明:
end
原因是10
是11:10
(虽然你不能将它用作stanalone变量),{{1}}给出一个空数组。
答案 1 :(得分:0)
简短的回答是肯定的,你可以在parfor中调用一个函数。
长期的答案是parfor仅在parfor中的每次迭代独立于其他迭代时才有效。当不是这种情况时,Matlab会检查以捕获;虽然我不知道他们有多全面。在您的示例中,每个foo()调用可以独立运行,并将其返回值存储在Mat的特定位置,该位置不会被任何其他parfor迭代写入或读取,因此它应该可以工作。
如果foo()正在读取Mat中的值,则会发生故障。例如,如果parfor同时运行4次迭代,并且在每次迭代中,foo()从Mat(1)读取然后将新值写入Mat(1),该值基于它读取的内容,读取的时间/ writes会改变输出值,matlab应该标记它。