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