【发布时间】:2011-06-05 14:01:46
【问题描述】:
我正在用 C++ 重写一些渲染 C 代码。旧的 C 代码基本上计算它需要的所有内容并在每一帧渲染它。新的 C++ 代码改为预先计算所需的内容并将其存储为链表。
现在,实际的渲染操作是翻译、颜色更改和调用 GL 列表。
虽然执行链表中的操作应该非常简单,但结果方法调用似乎比旧版本花费的时间更长(每次都会计算所有内容 - 我当然确保新版本不是重新计算)。
奇怪的事情?它执行的 OpenGL 操作比旧版本少。但它变得更奇怪了。当我为每种类型的操作添加计数器,并在方法结束时添加一个很好的旧 printf 时,它变得更快 - gprof 和手动测量都证实了这一点。
我还费心查看了 G++ 在这两种情况下生成的汇编代码(有和没有踪迹),并且没有重大变化(这是我最初的怀疑)——唯一的区别是多了几个堆栈词分配给计数器,增加所述计数器,并准备 printf 然后跳转到它。
同样,这适用于 -O2 和 -O3。我在 Ubuntu Maverick 上使用 gcc 4.4.5 和 gprof 2.20.51。
我想我的问题是:发生了什么事?我究竟做错了什么?是不是有什么东西让我的测量结果和 gprof 都丢了?
【问题讨论】:
-
那么分析告诉了没有计数器的版本?顺便说一句,我推荐 valgrind+callgrind 作为分析器,而 kcachegrind 作为可视化工具。
-
在没有计数器的版本中,渲染函数的平均时间为0.02ms(总计)。在带计数器的版本中,它不注册(总共 0.00 毫秒)。谢谢,我会试试 valgrind(但上次我尝试用它来检查同一个程序的内存泄漏时,它会导致使用专有的 nVidia 驱动程序崩溃)。
-
我还会尝试获取详细的配置文件,包括源代码的各个行。
-
如果分析这么简单,每个人都会随机放置计数器:P
-
每个 OpenGL 调用的计时仅衡量将操作添加到执行批处理所需的时间。但在您的情况下真正重要的是总渲染时间,即从帧的第一个 OpenGL 调用到完成 glFinish 调用的时间。我很确定,如果您比较程序的两个版本,那么在一个版本中调用 OpenGL 所需的额外时间将补偿更长的时间,直到 glFinish() 在另一个版本中返回。