考虑以下简单的速度测试arrayfun:
T = 4000;
N = 500;
x = randn(T, N);
Func1 = @(a) (3*a^2 + 2*a - 1);
tic
Soln1 = ones(T, N);
for t = 1:T
for n = 1:N
Soln1(t, n) = Func1(x(t, n));
end
end
toc
tic
Soln2 = arrayfun(Func1, x);
toc
Run Code Online (Sandbox Code Playgroud)
在我的机器上(Linux Mint 12上的Matlab 2011b),该测试的输出是:
Elapsed time is 1.020689 seconds.
Elapsed time is 9.248388 seconds.
Run Code Online (Sandbox Code Playgroud)
什么了?!?arrayfun虽然公认的解决方案更清洁,但速度要慢一个数量级.这里发生了什么?
此外,我做了类似的测试方式cellfun,发现它比显式循环慢约3倍.同样,这个结果与我的预期相反.
我的问题是:为什么是arrayfun和cellfun这么多慢?鉴于此,有没有充分的理由使用它们(除了使代码看起来很好)?
注意:我说的是arrayfun这里的标准版本,而不是并行处理工具箱中的GPU版本.
编辑:为了清楚起见,我知道 …
假设我想将一个单元格数组的每个元素A与一个系数相乘k.我可以这样做:
A = cellfun(@(x) k*x, A, 'UniformOutput', false)
Run Code Online (Sandbox Code Playgroud)
但这非常缓慢.有更快更好的方法吗?单元阵列元素是可变长度向量,因此cell2num不适用.
编辑:基于fpe对for循环的推荐,这是一个示例基准.从这些数据开始
A = arrayfun(@(n) rand(n,1), randi(5,1000,1000), 'UniformOutput',false);
Run Code Online (Sandbox Code Playgroud)
cellfun上面的调用需要9.45 seconds,而for循环:
A2 = cell(size(A));
for i = 1:size(A,1), for j = 1:size(A,2), A2{i,j} = A{i,j}*k; end; end
A = A2;
Run Code Online (Sandbox Code Playgroud)
需要1.67 seconds,这是一个重大的进步.我仍然更喜欢几个数量级的东西.(我也不明白为什么Matlab解释器无法像for循环一样快地进行cellfun调用.它们在语义上是相同的.)
编辑2: Amro建议制作一个单循环的速度要快得多:
for i = 1:numel(A), A{i} = A{i}*k; end
Run Code Online (Sandbox Code Playgroud)
需要1.11 seconds,如果我pack在它之前运行,只是调整内存0.88 seconds.
实现MEX函数实现这一点实际上并没有好多少:0.73 seconds,(0.53 seconds …
我对cellfunMATLAB 中的函数有疑问。
我什么时候/为什么要使用它,什么时候我也可以放弃它?
一个简单的例子:假设我有一个 cell a,我想找到 中所有值的平均值a。
a{1} = [1 2;3 4];
a{2} = [1 2 3;4 5 6; 7 8 9];
Run Code Online (Sandbox Code Playgroud)
我的方法是这样的:
mean([a{1}(:); a{2}(:)])
Run Code Online (Sandbox Code Playgroud)
什么是合适的cellfun版本,它会更好吗?
我试过做这样的事情,(显然不起作用):
mean_a = mean(cellfun(@mean, a,'UniformOutput',0))
Run Code Online (Sandbox Code Playgroud)
谢谢!
我有一个数组:
a = [109, 894, 566, 453, 342, 25]
Run Code Online (Sandbox Code Playgroud)
和另一个子索引的单元格数组a,表示为:
subs = { [1,3,4], [2,5,6], [1,3], [3,4], [2,3,4], [6] };
Run Code Online (Sandbox Code Playgroud)
我想避免for循环通过MATLAB计算以下求和:
for i=1:6
sums_a(i) = sum(a(subs{i}));
end
Run Code Online (Sandbox Code Playgroud)
有没有快速的方法arrayfun来实现这个?谢谢.
所以我在MATLAB中有2个矩阵.如果其中一个是100 X 2矩阵,如下所示:
[a b]
[13 19]
[21 39]
[35 45]
Run Code Online (Sandbox Code Playgroud)
等.等.
另一个矩阵是NX 1矩阵,其值如下:
[1]
[3]
[5]
[7]
Run Code Online (Sandbox Code Playgroud)
等.等.
我要做的是找到第二个矩阵的'a'到'b'的所有元素的Mean值.
到目前为止我得到的是:(如果我的第一个矩阵被称为:MATRIX1
第二个矩阵称为:MATRIX2)
a= MATRIX1(1:1)
b= MATRIX1(1:2)
values = MATRIX2(a:b)
mean(values)
Run Code Online (Sandbox Code Playgroud)
这给了我我想要的,从a到b的值的平均值.但是如何创建循环以便我可以自动为MATRIX 1中的所有行执行此操作?
谢谢!
更新:我想出了如何获得循环,但现在我不知道如何获取所有值并使其成为100 X 1矩阵.这是我使用的代码:
c= size(MATRIX1,1);
for k= 1:c;
a= MATRIX1(k,1);
b= MATRIX1(k,2);
values= MATRIX2(a:b);
d= mean(values)
end
Run Code Online (Sandbox Code Playgroud)
有了这个,我得到100的d值.如何将这些值放入100 X 1矩阵?
我有一个像这样的单元格数组:
a = {[1 2 3]; [4 5]; [6 7 8 9]};
Run Code Online (Sandbox Code Playgroud)
并希望在每个单元格的开头插入10,以便:
>> a{:}
ans =
10 1 2 3
ans =
10 4 5
ans =
10 6 7 8 9
Run Code Online (Sandbox Code Playgroud)
没有任何for循环可以做到吗?