Matlab 使用统计工具箱,数据集数组索引速度非常慢

Matlab 使用统计工具箱,数据集数组索引速度非常慢,matlab,Matlab,为什么索引到数据集数组的速度如此之慢?dataset.subsref函数的峰值显示数据集的所有列都存储在单元格数组中。然而,单元索引比数据集索引快得多,数据集索引只是在引擎盖下索引到单元数组中。我猜这与MATLAB OOP的一些开销有关。有没有办法加快速度 %%使用R2011a、PCWIN64 功能加速关闭;%关闭JIT dat=(1:1e6)'; dat2=repmat({'abc'},1e6,1); celldat={dat dat2}; ds=数据集(dat,dat2); N=1e2; 抽

为什么索引到数据集数组的速度如此之慢?dataset.subsref函数的峰值显示数据集的所有列都存储在单元格数组中。然而,单元索引比数据集索引快得多,数据集索引只是在引擎盖下索引到单元数组中。我猜这与MATLAB OOP的一些开销有关。有没有办法加快速度

%%使用R2011a、PCWIN64
功能加速关闭;%关闭JIT
dat=(1:1e6)';
dat2=repmat({'abc'},1e6,1);
celldat={dat dat2};
ds=数据集(dat,dat2);
N=1e2;
抽搐;
对于j=1:N
tmp=celldat{2};
结束
toc;
抽搐;
对于j=1:N
tmp2=ds.dat2;%dataset.subsref第262行花费2.778秒
结束
toc;
功能加速打开;%重新启用JIT
运行时间为0.000165秒。
运行时间为2.778995秒。
编辑:我已经更新了示例,使其更像我看到的问题。在dataset.subsref的第262行上花费了大量时间——“b=A.data{varIndex};”。这对我来说很奇怪,因为这是一个简单的单元格解引用。我想知道是否有一个OOP技巧可以让我索引到“a.data”,而不会产生奇怪的开销

EDIT2:根据安德鲁的建议,我已将此作为bug提交给MatWorks。如果我听到他们的消息,我会更新的


EDIT3:Matlab回应说,他们现在已经意识到这个问题,并将在未来的版本中修复它。他们注意到问题是特定于单元阵列的,如果可能的话,尽量避免它们。

是的,您很可能看到Matlab OOP方法调用的开销。与单元格索引或其他一些语言中的方法调用相比,它们的成本很高。每次调用的.513872秒/1e4~=51微秒,这是几个MCOS方法调用的近似成本;在我见过的机器上,每台大约5-15微秒。这看起来像是subsref()调用本身的方法开销,以及它依次调用的其他方法和属性访问

有关详细信息和讨论,请参阅:

除了对代码进行结构化以尽量减少对“ds.dat”或其他方法的调用之外,我不知道有什么方法可以加快这一过程。如果可能,在处理数据集时,调用“ds.dat”一次,将其保存在局部变量中并在那里处理,然后将其推回到ds对象中

警告:我不知道“功能加速”有什么作用,也不知道它会如何影响这些计时

编辑:我像里奇建议的那样把它扔进了剖析器。在我的R2009b上,大约一半的时间是方法调用开销,其余的时间是find()、strcmp()和subsref中的其他操作;subsref不依次调用任何其他方法


编辑2:修改后的示例显示了更高的计时。方法调用开销并不能解释所有这些。

在MATLAB profiler下它是什么样子?+1 Richie的评论是对任何MATLAB性能问题的最佳答案。90%以上的时间都花在dataset.subsref的第262行上,这很奇怪b/c这是一个简单的单元格取消引用。不幸的是,我给出的例子太简单,无法说明这一点。我将更新一个更现实的例子。@Rich C:“b=a.data{varIndex}”不是简单的单元格取消引用。“.”部分是MCOS对象字段访问,随后是“{}”单元格取消引用。我对dataset.subsref进行了黑客攻击,将其分为两行:“tmp=a.data;b=tmp{varIndex};”并对其进行了重新分析。所有时间都花在“a.data”字段访问上。同样,MCOS开销。等等,只有1e2通过了修改后的代码?这是惊人的缓慢。对于subsref中的“a.data”字段访问,这是20毫秒,而不是微秒。除了正常的开销之外,这里还发生了一些可疑的事情。看起来时间与数据有关。例如,如果我把它改为“dat=42;dat2={'foo'};”,那么它会变快。这几乎就像是写时拷贝优化不起作用,它正在进行数据的大拷贝。是的,保存ds.dat是一个节省时间的好方法。如果我知道循环中需要相同的列,我总是这样做。accel off关闭JIT,因此不会扭曲单元阵列循环的计时。