最好的量化答案,我可以看到的是:
gridx = arrayfun(@(grix)find((grnum(:)==grix) & (value(:)==grvalue(grix)),1),unique(grnum));
,但我不能说这是一个“快”矢量化的解决方案。 arrayfun
真的很有用,但通常不会比循环更快。
但是,最快的答案并不总是矢量化的。如果我重新实现代码,你写它,但有一个更大的数据集:
nValues = 1000000;
value = floor(rand(nValues,1)*100000);
group = num2cell(char(floor(rand(nValues,1)*4)+'a'));
tic;
[grnum, grname] = grp2idx(group);
grvalue = accumarray(grnum,value,[],@max);
toc;
我的电脑给我的0.886秒抽动/ TOC时间。 (注意,所有tic/tock时间来自文件中定义的函数的第二次运行,以避免一次性生成pcode。)
添加“矢量化”(真的是arrayfun
)一行gridx计算导致tic/tock时间为0.975秒。还不错,另外一项调查显示大部分时间都在拨打grp2idx
电话。
如果我们重新实现这个作为一个非矢量化,简单的循环,包括gridx
计算,像这样:
tic
[grnum, grname] = grp2idx(group);
grvalue = -inf*ones(size(grname));
gridx = zeros(size(grname));
for ixValue = 1:length(value)
tmpGrIdx = grnum(ixValue);
if value(ixValue) > grvalue(tmpGrIdx)
grvalue(tmpGrIdx) = value(ixValue);
gridx(tmpGrIdx) = ixValue;
end
end
toc
抽动/ TOC时间约为0.847秒,稍微比原来的代码快。
采取这种有点进一步,大部分时间出现在细胞阵列的存储器访问丢失。例如:
tic; groupValues = double(cell2mat(group')); toc %Requires 0.754 seconds
tic; dummy = (cell2mat(group')); toc %Requires 0.718 seconds
如果您最初定义组名称为数字阵列(例如,我将使用groupValues
正如我上面所定义它们),该时间减少了不少,甚至使用相同的代码:
groupValues = double(cell2mat(group')); %I'm assuming this is precomputed
tic
[grnum, grname] = grp2idx(groupValues);
grname = num2cell(char(str2double(grname))); %Recapturing your original names
grvalue = -inf*ones(size(grname));
gridx = zeros(size(grname));
for ixValue = 1:length(value)
tmpGrIdx = grnum(ixValue);
if value(ixValue) > grvalue(tmpGrIdx)
grvalue(tmpGrIdx) = value(ixValue);
gridx(tmpGrIdx) = ixValue;
end
end
toc
这产生了0.16秒的tic/tock时间。
你使用哪种matlab版? – Jonas 2013-03-15 21:04:42
@Jonas:2012b,Windows7 x64。 – yuk 2013-03-15 23:19:35