1

我有一个数据可视化应用程序(平行坐标)。这涉及在屏幕上绘制大量线条。该应用程序适用于庞大的数据集。测试数据集涉及约 250 万行(精确到 2527700 行)。屏幕会杂乱无章,但会显示一些图案。该应用程序具有沿 X 和 Y 缩放的功能。在典型的缩放级别下,它绘制大约 300K 线。该应用程序是用 Qt 编写的,渲染所花费的时间是可观的。典型数字是(以毫秒为单位的时间)

耗时:496 画了 1003226 行

耗时:603 画了 1210032 行

耗时:112 画了 344582 行

耗时:182 画了 387960 行

耗时:178 画了 361424 行

耗时:222 画了 676470 行

耗时:171 画了 475652 行

耗时:251 画了 318709 行

所用时间:5 绘制 14160 行

耗时:16 绘制 27233 行

以下代码段用于对绘制的线段进行计时和计数。渲染发生在屏幕外图像(格式为 Format_ARGB32_Premultiplied 的 QImage)。QImage 的大小最大为 1366 x 768。分段类型为 QVector。

QTime m_timer;
m_timer.start();
painter.drawLines(segments);
qDebug() << "Time taken: " << m_timer.elapsed();
painter.end();
qDebug() << "Drew " << segments.size();

此 QImage 被缓存以保存将来的绘图。我从未使用过 DirectX。直接 2D 渲染是否会比我已经拥有的提供更多的性能优势。有什么办法可以改善这些数字吗?

如果直接 2D 渲染可以提高这些数字,使用什么技术堆栈?使用 C#/SharpDX 会更好吗?我问这个是因为 Qt 只能通过翻译来执行 DirectX(不确定成本是多少),并且由于应用程序主要是 windows C# 可能会简化开发人员。过程。

4

3 回答 3

2

不知道 Qt,但对于 Direct2D,在 Windows 7 上绘制数百万条抗锯齿线(没有最新的 IE10/SP 更新)不会有很好的性能。在 Windows 8 上,Direct2D 略有改进,但我不确定它能否处理这样的速率。如果你想获得更好的性能,你必须直接使用 Direct3D 和 MSAA 表面,或者像 FXAA 那样的一些 screespace 后效,或者使用像 GPAA/GBAA 这样的几何感知抗锯齿技术。检查“实时抗锯齿的过滤方法”最先进的实时抗锯齿技术的综合列表。

于 2013-01-25T04:13:14.310 回答
2

最好创建自己的画线函数,直接在 QImage 内存缓冲区上操作。在那里你可以做出一些 Qt 的画家可能无法做到的假设并获得更好的性能。然后使用 QGLWidget 对图像进行 blit 以消除锯齿(并且可能缩放?)。

良好的线条绘制代码:http ://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm#Simplification 。尽管对于 C++ 和内存缓冲区的实现,它可以通过用单指针替换x0y0协调来进一步优化。

最重要的是,你可以在你的行循环中内联画线,并且在迭代超过一百万行时有零函数调用。

如果你让 blitting 部分做抗锯齿,你可以只为每个像素设置一个内存字,而不用检查它是什么类型的笔等。

还可以将硬件放大到任何所需的目标分辨率,您可以自由优化 QImage 大小以获得所需的图案,而不是在屏幕上显示它。

如果您可以让线条主要按 Y 坐标排序,这将有助于缓存,因为设置连续线条的像素将在 QImage 缓冲区的内存中更接近。

不管你怎么做,启动优化(gcc 的-O3 标志,不确定 MS 编译器),至少对于 gcc,默认不是 max。

您可以做的另一件事是在每个图像级别并行绘图,即使使用 QPainter 也可以。允许在主线程以外的 QImage 上绘图,并且 Qt 可以轻松地将 QImages 作为信号参数从绘图线程发送到 GUI 线程。您所做的是对 CPU 和内存的严重限制,因此最好将绘图线程数与实际核心数相同,而不是计算超线程。

于 2013-01-25T04:44:37.417 回答
1

也许我不会直接回答你的问题,但是:

  • 我猜想,Qt 使用标准系统例程来执行图形操作,所以这里指的是 GDI 和/或 GDI+。如果速度很快,它们都不会在 CPU 上进行所有计算。另一方面,来自 DirectX11+ 的 Direct2D 尝试尽可能使用 GPU 能力加速绘图,因此它可能会运行得更快。

  • 我不太了解 Qt,但我想,您应该能够检索您想要以某种方式绘制的窗口(=控件)的句柄(即使这意味着使用 WinAPI - 总有办法)。如果是这样,您可以绕过所有 Qt 机制并使用 DirectX 直接在该窗口上绘图,而无需额外开销。

  • 至于 SharpDX - 我不知道存在这样的库,感谢您提供信息。他们发表了一篇关于操作性能的论文,你可能想看看:http ://code4k.blogspot.com/2011/03/benchmarking-cnet-direct3d-11-apis-vs.html 。无论如何,它似乎是一个或多或少简单的 DirectX 标头包装器,因此它不应该给您的应用程序增加太多开销(除非性能非常关键)。

于 2013-01-24T09:42:48.493 回答