7

这是关于 MATLAB 如何花费非常不同的时间来绘制相同的东西——以及为什么。

我在 3D 空间中生成 10000 个点:

X = rand(10000, 1);
Y = rand(10000, 1);
Z = rand(10000, 1);

然后我使用四种不同方法中的一种来绘制它,以创建如下图:

替代文字

我关闭了所有数字并在每次运行之间清除了工作空间以确保公平。

使用 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在时间安排中包含了命令——但这对时间几乎没有影响。

4

3 回答 3

6

scatter3运行所需时间与编译所需时间之间的主要区别在于编译plot3的事实,而解释的事实(正如您在编辑函数时所看到的那样)。如果也编译,速度差异会很小。plot3scatter3scatter3

循环绘图与一次性绘图所需的时间之间的主要区别在于,您将句柄作为轴的子项添加到绘图中(看看 的输出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在循环中使用可能成为最好的(虽然很慢)的解决方案。

于 2010-11-06T00:59:12.357 回答
6

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

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

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

于 2010-11-06T01:39:02.120 回答
4

好吧,如果你想控制每个点的颜色,bulk scatter 会更快,因为你需要单独调用 plot。

另外,我不确定你的时间信息是否准确,因为你还没有打电话drawnow,所以实际的绘图可能会在 之后进行toc

总之:

  • plot3最快,因为它在许多不同的位置绘制相同的标记
  • scatter3绘制许多不同的标记,因为标记的大小和颜色(允许)随每个点而变化
  • 在循环中调用真的很慢,因为参数解析等必须重复进行,此外,随着点被添加到绘图中,轴必须重新计算
于 2010-11-06T00:23:21.713 回答