【发布时间】:2011-12-10 11:35:30
【问题描述】:
我刚刚学习 MATLAB,我发现很难理解循环与矢量化函数的性能因素。
在我之前的问题中:Nested for loops extremely slow in MATLAB (preallocated) 我意识到使用矢量化函数与 4 个嵌套循环相比,在运行时间上产生了 7 倍的差异。
在该示例中,不是循环遍历 4 维数组的所有维度并计算每个向量的中值,而是调用 median(stack, n) 更简洁、更快,其中 n 表示中值函数的工作维度。
但中位数只是一个非常简单的例子,我很幸运它实现了这个维度参数。
我的问题是,您如何自己编写一个与实现了这个维度范围的函数一样有效的函数?
例如,您有一个函数my_median_1D,它只适用于一维向量并返回一个数字。
你如何编写一个函数my_median_nD,它的作用类似于 MATLAB 的中位数,通过一个 n 维数组和一个 “工作维度” 参数?
更新
我找到了计算高维中位数的代码
% In all other cases, use linear indexing to determine exact location
% of medians. Use linear indices to extract medians, then reshape at
% end to appropriate size.
cumSize = cumprod(s);
total = cumSize(end); % Equivalent to NUMEL(x)
numMedians = total / nCompare;
numConseq = cumSize(dim - 1); % Number of consecutive indices
increment = cumSize(dim); % Gap between runs of indices
ixMedians = 1;
y = repmat(x(1),numMedians,1); % Preallocate appropriate type
% Nested FOR loop tracks down medians by their indices.
for seqIndex = 1:increment:total
for consIndex = half*numConseq:(half+1)*numConseq-1
absIndex = seqIndex + consIndex;
y(ixMedians) = x(absIndex);
ixMedians = ixMedians + 1;
end
end
% Average in second value if n is even
if 2*half == nCompare
ixMedians = 1;
for seqIndex = 1:increment:total
for consIndex = (half-1)*numConseq:half*numConseq-1
absIndex = seqIndex + consIndex;
y(ixMedians) = meanof(x(absIndex),y(ixMedians));
ixMedians = ixMedians + 1;
end
end
end
% Check last indices for NaN
ixMedians = 1;
for seqIndex = 1:increment:total
for consIndex = (nCompare-1)*numConseq:nCompare*numConseq-1
absIndex = seqIndex + consIndex;
if isnan(x(absIndex))
y(ixMedians) = NaN;
end
ixMedians = ixMedians + 1;
end
end
您能否向我解释一下与简单的嵌套循环相比,为什么这段代码如此有效?就像其他函数一样,它具有嵌套循环。
我不明白怎么会快 7 倍,还有,为什么这么复杂。
更新 2
我意识到使用中位数并不是一个很好的例子,因为它本身就是一个复杂的函数,需要对数组进行排序或其他巧妙的技巧。我用平均值重新进行了测试,结果更加疯狂: 19 秒对 0.12 秒。 这意味着 sum 的内置方式比嵌套循环快 160 倍。
我真的很难理解一种行业领先的语言如何根据编程风格有如此极端的性能差异,但我看到下面的答案中提到的几点。
【问题讨论】:
-
在 Matlab 命令提示符下键入“open median”,看看 Mathworks 是如何做到的!然而,他们作弊 - sort(X, dim) 是内置的。
标签: performance matlab loops for-loop vectorization