【问题标题】:how to pass one array as parameter in arrayfun in matlab?如何在matlab的arrayfun中将一个数组作为参数传递?
【发布时间】:2013-07-15 22:37:58
【问题描述】:

我将两个矩阵 A(大小为 nxn)和 B(大小为 nxm)相乘。 matlab 中最简单的方法是

n = 1000;
m = 500;
for k=1:n
  A(k, :) = (1:n)+k;
end
B = rand(n, m);
C = A*B; % C of the size nxm

但是,当 n 和/或 m 太大时,此代码会占用太多内存。所以我正在寻找一个矢量化版本的数组来实现它

n = 1000;
m = 500;
B = rand(n, m);
func0 = @(k, colv) [(1:n)+k]*colv;
func1 = @(V) arrayfun(func0, 1:n, V);
func1(B)

但它不起作用。它说尺寸不匹配。有人有什么建议吗?

【问题讨论】:

  • 你能再解释一下为什么你觉得C = A * B不合适吗?

标签: matlab vectorization


【解决方案1】:

我不会为此使用任何花哨的东西,只是分解正在执行的线性代数。

C = zeros(n,m);
for k = 1:n
    C(k,:) = ((1:n)+k)  *  B;
end

或者,稍微详细一点

C = zeros(n,m);
for k = 1:n
    A_singleRow = ((1:n)+k);
    C(k,:) = A_singleRow*  B;
end

对于疯狂的大尺寸(听起来像您有),请尝试重新制定问题,以便您可以迭代列,而不是行。 (Matlab 使用以列为主的矩阵存储,这意味着同一列中的元素在内存中是相邻的。通常对此进行细化属于过度优化的领域,但可能不适合您。)

例如,您可以如下构造Ctranspose

Ctranspose = zeros(m,n);  %Note reversed order of n, m
Btranspose = B';          %Of course you may want to just create Btranspose first
for k = 1:n
    A_singleRowAsColumn = ((1:n)'+k);
    Ctranspose(:,k) = Btranspose * A_singleRowAsColumn;
end

arrayfuncellfun 工具对于功能化 for 循环非常有用,可用于使代码更清晰。但是,在尝试压缩性能时,它们通常没有用。即使调试了匿名函数/arrayfun 实现,我怀疑它也需要大致相同的内存使用量。

【讨论】:

  • 你说得对,性能真的没有matlab中直接使用矩阵乘法那么快。但是使用的内存比原来的情况要少。在我的代码中,矩阵是如此之大(使用超过 30GB 甚至更多),您的代码或 arrayfun 将节省 1/3 内存。但是为了效率,使用循环不如 arrayfun 快(虽然它不容易理解)。我的代码正在模拟一个大矩阵,它总共使用了 100GB 并运行了 500 多个小时,它太大而且用直接矩阵乘法运行太慢,所以我需要一个交替方案
  • 这有点疯狂。我添加了另一件事来尝试,与 Matlab 中的列优先排序有关。此外,请确保您确实适合您的物理记忆。运行[~,x]=memory,并确保x.PhysicalMemory.Available 足够大。
  • 谢谢。是的,它确实符合我的记忆。代码在集群中运行,内存很大,但只有部分内存会分配给每个用户和任务,所以我正在寻找一种平衡内存和性能的方法。
猜你喜欢
  • 2011-02-13
  • 1970-01-01
  • 2021-06-02
  • 1970-01-01
  • 1970-01-01
  • 2019-10-31
  • 1970-01-01
  • 2011-09-25
  • 2014-06-04
相关资源
最近更新 更多