Matlab 如何在4层嵌套for循环块中实现并行for

Matlab 如何在4层嵌套for循环块中实现并行for,matlab,for-loop,parallel-processing,Matlab,For Loop,Parallel Processing,我必须计算相当多模型的大型数据集的std和mean。最后一个循环块嵌套到四个级别 这就是它看起来的样子: count = 1; alpha = 0.5; %%%Below if each individual block is to be posterior'd and then average taken c = 1; for i = 1:numel(writers) %no. of writers for j = 1: numel(test_feats{i}) %no. of i

我必须计算相当多模型的大型数据集的
std
mean
。最后一个循环块嵌套到四个级别

这就是它看起来的样子:

count = 1;
alpha  = 0.5;
%%%Below if each individual block is to be posterior'd and then average taken 
c = 1;
for i = 1:numel(writers) %no. of writers
    for j = 1: numel(test_feats{i}) %no. of images
        for k = 1: numel(gmm) %no. of models
            for n = 1: size(test_feats{i}{j},1)
                [~, scores(c)] = posterior(gmm{k}, test_feats{i}{j}(n,:));
                c = c + 1;
            end
            c = 1;
            index_kek=find(abs(scores-mean(scores))>alpha*std(scores));
            avg = mean(scores(index_kek)); %using std instead of mean... beacause of ..reasons
            NLL(count) = avg;
            count = count + 1;
        end
        count = 1; %reset count
        NLL_scores{i}(j,:) = NLL; 

    end
    fprintf('***score for model_%d done***\n', i)
end
它可以工作并给出所需的结果,但需要3天才能给出最终的计算结果,即使在我的i7处理器上也是如此。在处理过程中,任务管理器告诉我只有20%的cpu被使用,因此我宁愿在cpu上增加负载,以更快地得到结果

如果我想使最外层的循环成为parfor,而使其余的循环保持正常,那么我需要做的就是插入整数限制,而不是函数调用,例如
size
numel

因此,进行这些更改后,上述代码将变为:

count = 1;
alpha  = 0.5;
%%%Below if each individual block is to be posterior'd and then average taken 
c = 1;
num_writers = numel(writers);
num_images = numel(test_feats{1});
num_models = numel(gmm);
num_feats = size(test_feats{1}{1},1);

parfor i = 1:num_writers %no. of writers
    for j = 1: num_images %no. of images
        for k = 1: num_models %no. of models
            for n = 1: num_feats
                [~, scores(c)] = posterior(gmm{k}, test_feats{i}{j}(n,:));
                c = c + 1;
            end
            c = 1;
            index_kek=find(abs(scores-mean(scores))>alpha*std(scores));
            avg = mean(scores(index_kek)); %using std instead of mean... beacause of ..reasons
            NLL(count) = avg;
            count = count + 1;
        end
        count = 1; %reset count
        NLL_scores{i}(j,:) = NLL; 

    end
    fprintf('***score for model_%d done***\n', i)
end

在我的例子中,这是实现
parfor
的最佳方法吗?它可以进一步改进或优化吗?

我现在无法在Matlab中进行测试,但它应该接近一个工作解决方案。它减少了循环次数,并更改了一些实现细节,但总体而言,它的执行速度可能与以前的代码一样快(甚至更慢)

如果gmm和test_壮举占用大量内存,那么parfor能够确定哪些数据需要交付给哪些工作人员是很重要的。如果检测到低效的内存访问,IDE应该警告您。如果num_writer远小于CPU中的内核数,或者如果它只是稍微大一点(例如4个内核5个writer大约需要8个writer),则此修改尤其有用


可以肯定的是,4嵌套循环远远不是任何东西的最佳实现。“最佳”方式很难选择,因为它取决于每个工人需要发送的信息以及代码。感觉你的代码和数据都很高,所以实际上没有人能够准确地回答这个问题。祝你好运!在每个循环之前显式声明
numel
的更改不会改变任何内容;不要将
i
j
用作;我很确定通过矢量化可以避免一些循环,但是如果没有你的数据,我无法检查。请注意:
parfor
不是魔术。最好先完全优化串行代码(从而使其矢量化),然后再进行并行处理。
[i_writer i_image i_model] = ndgrid(1:num_writers, 1:num_images, 1:num_models);
idx_combined = [i_writer(:) i_image(:) i_model(:)];
n_combined = size(idx_combined, 1);

NLL_scores = zeros(n_combined, 1);

parfor i_for = 1:n_combined
    i = idx_combined(i_for, 1)
    j = idx_combined(i_for, 2)
    k = idx_combined(i_for, 3)

    % pre-allocate
    scores = zeros(num_feats, 1)

    for i_feat = 1:num_feats
        [~, scores(i_feat)] = posterior(gmm{k}, test_feats{i}{j}(i_feat,:));
    end

    % "find" is redundant here and performs a bit slower, might be insignificant though
    index_kek = abs(scores - mean(scores)) > alpha * std(scores);
    NLL_scores(i_for) = mean(scores(index_kek));
end