Matlab 在大量矩阵上并行化或矢量化所有对所有操作?
我有大约5000个矩阵,行数相同,列数不同(20 x~200)。在动态规划算法中,这些矩阵必须相互比较 在这个问题上,我问了如何快速执行比较,得到了一个涉及2D卷积的极好答案。串行地、迭代地应用该方法,如下所示Matlab 在大量矩阵上并行化或矢量化所有对所有操作?,matlab,dynamic-programming,vectorization,parallel-processing,Matlab,Dynamic Programming,Vectorization,Parallel Processing,我有大约5000个矩阵,行数相同,列数不同(20 x~200)。在动态规划算法中,这些矩阵必须相互比较 在这个问题上,我问了如何快速执行比较,得到了一个涉及2D卷积的极好答案。串行地、迭代地应用该方法,如下所示 list = who('data_matrix_prefix*') H = cell(numel(list),numel(list)); for i=1:numel(list) for j=1:numel(list) if i ~= j
list = who('data_matrix_prefix*')
H = cell(numel(list),numel(list));
for i=1:numel(list)
for j=1:numel(list)
if i ~= j
eval([ 'H{i,j} = compare(' char(list(i)) ',' char(list(j)) ');']);
end
end
end
对于较小的数据子集来说是快速的(例如,对于9个矩阵,9*9-9=72次调用在~1s内进行,870次调用在~2.5s内进行)。然而,对所有数据进行操作需要近2500万次呼叫。
我还尝试使用deal()创建一个完全由数据中的下一个元素组成的单元格数组,因此我可以在单个循环中使用cellfun():
# who(), load() and struct2cell() calls place k data matrices in a 1D cell array called data.
nextData = cell(k,1);
for i=1:k
[nextData{:}] = deal(data{i});
H{:,i} = cellfun(@compare,data,nextData,'UniformOutput',false);
end
不幸的是,这实际上并没有更快,因为所有的时间都在compare()中。这两个代码示例似乎都不适合并行化。我很难弄清楚如何将变量切片。compare()完全矢量化;它专门使用矩阵乘法和conv2()(我的印象是,所有这些操作,包括cellfun(),都应该在MATLAB中使用多线程?) 有人看到(明确的)并行解决方案或更好的问题矢量化吗 注意
我意识到我的两个例子都是低效的——第一个如果计算三角形单元格数组,速度会快一倍,第二个仍然在计算自比较。但是,一个好的并行化所节省的时间更像是16倍(如果我在每个人的机器上安装MATLAB,则为72倍) 旁白
还有一个内存问题。我使用了两个eval将H的每一列附加到一个文件中,使用H1、H2等名称,然后清除Hi。不幸的是,保存速度非常慢…如果我理解正确,您必须执行5000^2矩阵比较吗?与其尝试并行比较函数,也许您应该考虑您的问题由5000^2个任务组成?Matlab并行计算工具箱支持基于任务的并行。不幸的是,我在PCT方面的经验是大型线性代数类型问题的并行化,所以我不能告诉你更多。文档无疑会给您带来更多帮助。如果我理解正确,您必须执行5000^2矩阵比较吗?与其尝试并行比较函数,也许您应该考虑您的问题由5000^2个任务组成?Matlab并行计算工具箱支持基于任务的并行。不幸的是,我在PCT方面的经验是大型线性代数类型问题的并行化,所以我不能告诉你更多。文档无疑会给您带来更多帮助。第二个示例可以很容易地切片,以便与并行处理工具箱一起使用。此工具箱在多达8个不同的本地处理器之间分配代码的迭代。如果要在集群上运行代码,还需要分布式计算工具箱
%# who(), load() and struct2cell() calls place k data matrices in a 1D cell array called data.
parfor i=1:k-1 %# this will run the loop in parallel with the parallel processing toolbox
%# only make the necessary comparisons
H{i+1:k,i} = cellfun(@compare,data(i+1:k),repmat(data(i),k-i,1),'UniformOutput',false);
%# if the above doesn't work, try this
hSlice = cell(k,1);
hSlice{i+1:k} = cellfun(@compare,data(i+1:k),repmat(data(i),k-i,1),'UniformOutput',false);
H{:,i} = hSlice;
end
第二个示例可以很容易地切片,以便与并行处理工具箱一起使用。此工具箱在多达8个不同的本地处理器之间分配代码的迭代。如果要在集群上运行代码,还需要分布式计算工具箱
%# who(), load() and struct2cell() calls place k data matrices in a 1D cell array called data.
parfor i=1:k-1 %# this will run the loop in parallel with the parallel processing toolbox
%# only make the necessary comparisons
H{i+1:k,i} = cellfun(@compare,data(i+1:k),repmat(data(i),k-i,1),'UniformOutput',false);
%# if the above doesn't work, try this
hSlice = cell(k,1);
hSlice{i+1:k} = cellfun(@compare,data(i+1:k),repmat(data(i),k-i,1),'UniformOutput',false);
H{:,i} = hSlice;
end
做
及
如果是这样,请更改循环
for i=1:numel(list)
for j=1:numel(list)
...
end
end
到
并处理对称性和同一性的情况。这将使您的计算时间减少一半。确实如此
及
如果是这样,请更改循环
for i=1:numel(list)
for j=1:numel(list)
...
end
end
到
并处理对称性和同一性的情况。这将使您的计算时间减少一半。比较
的功能是什么?列表中的示例行是什么?对于数据矩阵A和B,它计算A'*B并将乘积与单位矩阵进行卷积。对矩阵进行归一化处理;行和列包含从0到1的值,总和为1。比较得到的矩阵包含从-30到30的值,大致遵循极值分布。那么使用eval
的原因是什么?对不起,我想我误解了。上面我称之为list的变量将矩阵的名称作为其行。compare
do做什么?列表中的示例行是什么?对于数据矩阵A和B,它计算A'*B并将乘积与单位矩阵进行卷积。对矩阵进行归一化处理;行和列包含从0到1的值,总和为1。比较得到的矩阵包含从-30到30的值,大致遵循极值分布。那么使用eval
的原因是什么?对不起,我想我误解了。我在上面调用的列表变量的行是矩阵的名称。“由于nextData的使用方式,PARFOR循环无法运行。”此外,它不希望对数据进行切片(这是一个1D单元格数组)。它不会对数据进行切片,因为在调用cellfun时使用了整个数组数据。另外,我修复了nextData
的问题,谢谢……现在M-Lint很高兴。但repmat能否返回重复数据元素的单元格数组?它将它们连接在一起并创建一个大矩阵。@reve_etrange。哦!您需要使用数据(i)而不是数据{i}执行repmat。Fixed@reve_etrange:我还更新了解决方案,以便您只进行必要的比较“由于nextData的使用方式,PARFOR循环无法运行”。此外,它不希望切片数据(这是一个1D单元格数组)。它不会切片数据
,因为您在调用cellfun时使用了整个数组数据
。另外,我修复了nextData
的问题,谢谢……现在M-Lint很高兴。但repmat能否返回重复数据元素的单元格数组?它将它们连接在一起并创建一个大矩阵。@reve_etrange。哦!您需要使用数据(i)而不是数据{i}执行repmat。Fixed@reve_etrange:我还更新了t
for i=1:numel(list)
for j= i+1 : numel(list)
...
end
end