MATLAB scatter3, plot3 速度差异

7
这篇文章是关于MATLAB绘制同样内容时所需时间差异的原因。我在三维空间中生成了一万个点:
X = rand(10000, 1);
Y = rand(10000, 1);
Z = rand(10000, 1);

我随后使用了四种不同的方法之一来绘制图形,创建了如下所示的图形:

alt text

为了确保公正,我在每次运行之间关闭了所有图形并清除了工作区。 使用scatter3进行批量绘图:
>> tic; scatter3(X, Y, Z); drawnow; toc
Elapsed time is 0.815450 seconds.

使用scatter3进行个体绘图:

>> tic; hold on;
for i = 1:10000
    scatter3(X(i), Y(i), Z(i), 'b');
end
hold off; drawnow; toc
Elapsed time is 51.469547 seconds.

使用plot3进行批量绘图:

>> tic; plot3(X, Y, Z, 'o'); drawnow; toc
Elapsed time is 0.153480 seconds.

使用plot3进行单独绘图:

>> tic; hold on
for i = 1:10000
    plot3(X(i), Y(i), Z(i), 'o');
end
drawnow; toc
Elapsed time is 5.854662 seconds.

MATLAB在“长时间”例程中背后所做的事情是什么?使用每种方法的优缺点是什么?
编辑:感谢Ben Voigt的建议(请参见答案),我已在计时中包含了drawnow命令,但这对时间几乎没有影响。

有什么区别吗?plot3的批量处理时间增加了三个数量级! - Ben Voigt
3个回答

6

运行scatter3plot3所需的时间之间的主要区别在于,plot3是编译的,而scatter3是解释性的(当您编辑这些函数时,可以看到这一点)。如果scatter3也被编译,速度差异将会很小。

在循环中进行绘图所需的时间与一次性绘图的主要区别在于,将句柄添加为子项到坐标轴(查看get(gca,'Children')的输出),从而在循环内部增加了一个复杂的数组,这是我们都知道的缓慢操作。此外,你正在多次调用几个函数而不是只调用一次,从而需要额外的函数开销。

重新计算坐标轴限制并不是这里的问题。如果您运行

for i = 1:10000
    plot3(X(i), Y(i), Z(i), 'o');
    drawnow;
end

如果你强制Matlab在每次迭代时更新图形(这会使速度变慢很多),你会发现轴限制根本不会改变(因为默认的轴限制是0和1)。不过,即使轴限制最初不同,也不需要很多次迭代就可以与这些数据收敛。与省略hold on相比,后者需要更长时间绘图,因为轴在每一步重新计算。
为什么有这些不同的函数呢?scatter3允许你在一个句柄下绘制具有不同标记大小和颜色的点,而使用plot3需要使用循环并为每个点获得一个句柄,这不仅在速度上很昂贵,而且在内存方面也是如此。但是,如果你需要单独与不同的点(或点组)交互 - 也许你想为每个点添加一个单独的图例条目,也许你想能够单独打开和关闭它们等等 - 使用plot3循环可能是最好的(尽管速度较慢)解决方案。

谢谢,这真的澄清了关于速度差异的问题,特别是关于幕后发生的事情。 - Bill Cheatham

6

为了更快的方法,考虑第三个选项(直接使用低级函数LINE):

line([X,X], [Y,Y], [Z,Z], 'LineStyle','none', 'Marker','o', 'Color','b')
view(3)

以下是一些讨论绘图性能问题的文章:


5
除了你在UndocumentedMatlab.com提到的文章之外,还要注意下面这篇文章,它解释了当请求绘制100多个数据点时,scatter函数会出现意外行为:http://UndocumentedMatlab.com/blog/undocumented-scatter-plot-behavior/。 - Yair Altman

4

如果您想要控制每个点的颜色,批量散点图会更快,因为您需要分别调用plot。

另外,我不确定您的时间信息是否准确,因为您没有调用drawnow,所以实际绘图可能发生在toc之后。

总之:

  • plot3是最快的,因为它在许多不同的位置绘制相同的标记
  • scatter3绘制许多不同的标记,因为标记的大小和颜色(可以)随着每个点而变化
  • 循环调用非常慢,因为需要重复进行参数解析等操作,此外,当点添加到图中时,轴必须重新计算

非常有趣 - 那么MATLAB在调用后会随机绘制图形吗?再次问,为什么?MATLAB在其代码中做了什么来导致这种情况? - Bill Cheatham
几乎所有的GUI程序只有在接收到操作系统的绘图请求时才会绘制图形。这实际上是非常好的。我注意到你正在使用自动轴,因此hold on版本会为第一个点计算一个轴比例尺,当你添加下一个点时,它会计算一个新的轴比例尺,并且每次添加一个不在先前绘制的点范围内的新点时都会调整轴。如果它立即渲染,它将不得不绘制轴、刻度、标题等数百次,而不仅仅是一次。或者图形窗口可能被最小化或覆盖。 - Ben Voigt
啊哈,这很好知道。因此,每个新点的轴都被重新调整大小。我可以看出这会很耗时,谢谢。 - Bill Cheatham
当然,批量版本只是找到 XYZmin()max(),并设置轴。而你称之为单独绘图的 hold on 版本则需要不断重新计算轴。 - Ben Voigt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接