Matlab 在大量矩阵上并行化或矢量化所有对所有操作?

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

我有大约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
            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