这是输入数据:
% @param Landmarks:
% Landmarks should be 1*m struct.
% m is the number of training set.
% Landmark(i).data is a n*2 matrix
旧功能:
function Landmarks=CenterOfGravity(Landmarks)
% align center of gravity
for i=1 : length(Landmarks)
Landmarks(i).data=Landmarks(i).data - ones(size(Landmarks(i).data,1),1)...
*mean(Landmarks(i).data);
end
end
使用arrayfun的新函数:
function [Landmarks] = center_to_gravity(Landmarks)
Landmarks = arrayfun(@(struct_data)...
struct('data', struct_data.data - repmat(mean(struct_data.data), [size(struct_data.data, 1), 1]))...
,Landmarks);
end %function center_to_gravity
使用分析器时,我发现时间的使用是 NOT 我所期望的:
Function Total Time Self Time*
CenterOfGravity 0.011s 0.004 s
center_to_gravity 0.029s 0.001 s
有人可以告诉我为什么吗?
BTW ......我不能将“arrayfun”添加为我声誉的新标签。
答案 0 :(得分:4)
使用arrayfun
并不算作“代码化矢量化”,如每篇Matlab性能博客文章中所述。
如果您的.data
字段与所有地标条目的长度相同,您可以通过首先将所有数据放入单个DATASIZE-BY-LANDMARKSIZE martix,然后运行此命令来矢量化此代码
meanRemovedData = bsxfun(@minus, data, mean(data,1));
但是你失去了很多代码清晰度。 (我很确定bsxfun
通常具有类似矢量化的速度优势,但我今天早上没有进行任何测试。)
就其原因而言,我不是一个真正合适的人。但是,矢量化的许多优点依赖于执行连续的存储块的简单操作。存储在结构数组中的数据(我相信)存储为指向不同内存位置的指针数组,这就是为什么你可以在不重新分配整个结构数组的情况下更改Landmarks(i).data
的大小或类的原因。
答案 1 :(得分:3)
感谢Amro和Pursuit对我的问题充满热情。
我在Matlab的Jan Simon答案中获得最佳解决方案:
why arrayfun does NOT improve my struct array operation performance
有些观点可以改善效果:
最快的方法是使用这样的技巧:
m = sum(data,1)/ size(data,1); data(:,1)= data(:,1) - m(1);
答案 2 :(得分:1)
考虑以下三种实现(全部使用BSXFUN进行矢量化):
function s = func1(s)
for i=1:numel(s)
s(i).data = bsxfun(@minus, s(i).data, mean(s(i).data));
end
end
function v = func2(s)
v = arrayfun(@(ss) bsxfun(@minus,ss.data,mean(ss.data)), ...
s, 'UniformOutput',false);
v = struct('data',v);
end
function v = func3(s)
v = arrayfun(@(ss) struct('data',bsxfun(@minus,ss.data,mean(ss.data))), ...
s, 'UniformOutput',true);
end
说明:
这是一个比较时间的简单测试:
function testArrayStruct()
%# sample array of structures
s = struct('data',[]);
for i=5000:-1:1
s(i).data = rand(randi(1000),2);
end
%# timing
tic; v1 = func1(s); toc
tic; v2 = func2(s); toc
tic; v3 = func3(s); toc
%# check all have the same output
assert(isequal(v1,v2,v3))
end
结果:
Elapsed time is 0.357796 seconds. %# func1
Elapsed time is 0.427568 seconds. %# func2
Elapsed time is 0.537971 seconds. %# func3
所以你可以看到基于循环的解决方案实际上是最快的..