【问题标题】:Vectorizing MATLAB function向量化 MATLAB 函数
【发布时间】:2011-09-09 15:45:20
【问题描述】:

对于极点,我对 m = 1:Mn = 1:N 有双重求和带坐标rhophiz

我已经写了它的矢量化符号:

N = 10;
M = 10;
n = 1:N;
m = 1:M;

rho = 1;
phi = 1;
z = 1;

summ =  cos (n*z)  * besselj(m'-1, n*rho) * cos(m*phi)';

现在我需要重写这个函数来接受坐标rhophiz的向量(列)。我尝试了arrayfun、cellfun、简单的for循环——它们对我来说太慢了。我知道“MATLAB 数组操作技巧和窍门”,但作为 MATLAB 初学者,我无法理解 repmat 和其他函数。

任何人都可以建议矢量化解决方案吗?

【问题讨论】:

  • 能否详细说明每个变量的维度。 IE。 rho1xA 等,以及您期望输出的尺寸。首先,这有助于我们帮助您,其次,这有助于您帮助自己,因为合适的尺寸是使用 MATLAB 时首先要考虑的因素。

标签: matlab sum vectorization bessel-functions


【解决方案1】:

我认为您的代码已经很好地矢量化了(对于nm)。如果您希望此函数也接受 rho/phi/z 值的数组,我建议您只需在 for 循环中处理这些值,因为我怀疑任何进一步的矢量化都会带来显着的改进(加上代码会更难阅读)。

话虽如此,在下面的代码中,我尝试通过对 BESSELJ 和 COS 函数的一次调用(我将每个行/矩阵/第三维中的列)。它们的乘法仍然是done in a loop(确切地说是ARRAYFUN):

%# parameters
N = 10; M = 10;
n = 1:N; m = 1:M;

num = 50;
rho = 1:num; phi = 1:num; z = 1:num;

%# straightforward FOR-loop
tic
result1 = zeros(1,num);
for i=1:num
    result1(i) = cos(n*z(i)) * besselj(m'-1, n*rho(i)) * cos(m*phi(i))';
end
toc

%# vectorized computation of the components
tic
a = cos( bsxfun(@times, n, permute(z(:),[3 2 1])) );
b = besselj(m'-1, reshape(bsxfun(@times,n,rho(:))',[],1)');             %'
b = permute(reshape(b',[length(m) length(n) length(rho)]), [2 1 3]);    %'
c = cos( bsxfun(@times, m, permute(phi(:),[3 2 1])) );
result2 = arrayfun(@(i) a(:,:,i)*b(:,:,i)*c(:,:,i)', 1:num);            %'
toc

%# make sure the two results are the same
assert( isequal(result1,result2) )

我使用TIMEIT 函数进行了另一次基准测试(提供更公平的计时)。结果与前面一致:

0.0062407    # elapsed time (seconds) for the my solution
0.015677     # elapsed time (seconds) for the FOR-loop solution

请注意,随着您增加输入向量的大小,这两种方法将开始具有相似的时序(在某些情况下,FOR 循环甚至会获胜)

【讨论】:

  • 非常感谢。您的代码运行速度非常快。我将保留此代码 sn-p 作为bsxfunpermute 的示例。我尝试用 for 循环替换 arrayfun,我得到了额外快 2-10 倍的代码。似乎arrayfuncellfun 比普通的for循环慢。
【解决方案2】:

您需要创建两个矩阵,例如m_n_,以便通过选择每个矩阵的元素i,j,您可以获得mn 所需的索引。

大多数 MATLAB 函数都接受矩阵和向量,并逐个元素地计算它们的结果。因此,要产生一个双倍和,您可以通过 f(m_, n_) 并行计算总和的所有元素并将它们相加。

在您的情况下(请注意,.* 运算符执行矩阵的元素乘法)

N = 10;
M = 10;
n = 1:N;
m = 1:M;

rho = 1;
phi = 1;
z = 1;

% N rows x M columns for each matrix
% n_ - all columns are identical
% m_ - all rows are identical
n_ = repmat(n', 1,  M);
m_ = repmat(m , N,  1);

element_nm =  cos (n_*z) .* besselj(m_-1, n_*rho) .* cos(m_*phi);
sum_all = sum( element_nm(:) );

【讨论】:

  • 你好,尼姆罗德姆!谢谢您的回答。但这不是我的意思。我的意思是,rhophiz 将是向量,即 rho=0:4、phi=0:4、z=0: 4.您的代码不接受这些变量的向量。它给出了与我的代码相同的结果(对于 rhophiz 的标量值),但执行速度比我的慢 620 倍。我的变体意味着 {row N} * { matrix NM } * {col M} = {scalar}。这就是为什么我没有使用元素运算符(例如 .)。
猜你喜欢
  • 2012-10-15
  • 1970-01-01
  • 2018-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-18
  • 2011-12-10
相关资源
最近更新 更多