我正在学习MATLAB,发现难以理解循环和矢量化函数的性能因素。
在我之前提出的问题中:Nested for loops extremely slow in MATLAB (preallocated),我意识到使用矢量化函数与4个嵌套循环相比,运行时间快了7倍。
在这个例子中,不是遍历4维数组的所有维度并为每个向量计算中位数,而是用median(stack, n)调用方式更加简洁快速,其中n表示median函数的工作维度。
但是,median只是一个非常简单的示例,我很幸运它实现了这个维度参数。
我的问题是如何编写一个函数,使其像一个具有此维度范围实现的函数一样高效工作?
例如,您有一个仅针对1-D向量并返回数字的函数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秒。这意味着内置求和方法比嵌套循环快160倍。
对于我来说,真的很难理解为什么行业领先的语言在编程风格上具有如此极端的性能差异,但我看到了以下答案中提到的观点。