Matlab 中多重投影的快速算法

Fast Algorithm for Multiple Projections in Matlab

我的问题是在 Matlab 中快速执行许多低维投影 。我有一个数组 z,其维度为 (n,L,d);这些参数是按如下方式获得的。我取一个大小为 N 的输入数组,比如 N = [200, 200]n = prod(N) = 200*200 = 40,000d = numel(N) = 2;也就是说,n 是我的离散化网格中的点数,d 是输入数组的维度(例如图像,或来自高度图的平面)。然后我用 L 点离散化可能的高度(我的程序将输出 - 注意上面提到的高度图),比如 L = 32.

对于每个 i = 1:nj = 1:L,我想将向量 z(i,j,:) 投影到单位球上。* 目前,我有以下天真的代码:

z = reshape(z,[n,L,d]); z_norms = norms(z,2,3);
for i = 1:n
for j = 1:L
    z(i,j,:) = z(i,j,:)/max(1,z_norms(i,j));
end
end

函数norms(v,p,dim)沿维度dim取矩阵v的p范数(在本例中输出(n,L)矩阵)。

对于如何改进这一点,我有多种想法。一个想法如下:

for i = 1:n
for j = 1:L
normsquared = sum(z(i,j,:).^2)
if normsquared > 1
    z(i,j,:) = z(i,j,:)/sqrt(normsquared)
end
end
end

请注意,normsquared 每次都会被覆盖,因此它不会占用我的 space。当我在另一个问题上使用它时,它大大加快了这个过程;但是,我刚刚针对这个问题进行了测试,实际上情况更糟——大约慢了三倍;事实上,计算 normsquared 的时间大约是第一种情况下进行投影所用时间的两倍半!

奇怪的是,如果我将 sum(z(i,j,:).^2) 更改为 z(i,j,1)^2 + z(i,j,2)^2(在使用 d = 2 的情况下),那么它实际上比第一种(天真的)方法稍快......如果有人可以解释我也是这个,那就太好了!

如果有人对如何加快速度有任何建议,我将不胜感激!目前,我的程序 运行 大约 90% 的时间都花在了这上面!


*实际上,我想将它投影到 lambda 乘以单位球,其中 lambda 是另一个参数,但这不太可能对算法产生影响 - 只需将 z 除以 lambda,进行投影,然后乘以lambda,例如

您可以尝试用 parfor 循环替换内部 for 循环。 parfor 允许您在多核处理器上同时 运行 多次迭代。

http://nl.mathworks.com/help/distcomp/parfor.html

当您可以使用 bsxfun 将双 for 循环重写为 "vectorize" 操作时,无需使用 parfor

z = bsxfun(@rdivide,z,max(1,z_norms))

max 函数对 n×L z_norms 矩阵的阈值进行矢量化处理,使所有值都小于或等于 1。 z 是一个 3 维的 n×L×d 数组。 bsxfun 虚拟地在 z 的第三维上复制较低维 z_norms 矩阵 d 次,这样两者的逐元素划分 (rdivide) 可以是执行。结果是一个 n×L×d 数组。

profiling your code, rewriting loops to take advantage of Matlab's vectorization capabilities should be one of the first things you try to improve performance之后。