C++;使用OpenGL的性能怪异 我正在重写C++中的一些渲染C代码。旧的C代码基本上计算它所需要的一切,并在每一帧渲染它。新的C++代码代替预先计算它需要什么,并将其存储为链表。

C++;使用OpenGL的性能怪异 我正在重写C++中的一些渲染C代码。旧的C代码基本上计算它所需要的一切,并在每一帧渲染它。新的C++代码代替预先计算它需要什么,并将其存储为链表。,c++,opengl,g++,gprof,C++,Opengl,G++,Gprof,现在,实际的渲染操作是翻译、颜色更改和调用GL列表 虽然在链表中执行操作应该非常简单,但结果方法调用似乎比旧版本(每次都计算所有内容-我当然已经确保新版本不会重新计算)花费更长的时间 奇怪的事?它执行的OpenGL操作比旧版本少。但它变得更奇怪了。当我为每种类型的操作添加计数器,并在方法末尾添加一个好的旧printf时,它变得更快了——gprof和手动测量都证实了这一点 我还不厌其烦地查看了G++在这两种情况下生成的汇编代码(有跟踪和无跟踪),没有重大变化(这是我最初的怀疑)——唯一的区别是为计

现在,实际的渲染操作是翻译、颜色更改和调用GL列表

虽然在链表中执行操作应该非常简单,但结果方法调用似乎比旧版本(每次都计算所有内容-我当然已经确保新版本不会重新计算)花费更长的时间

奇怪的事?它执行的OpenGL操作比旧版本少。但它变得更奇怪了。当我为每种类型的操作添加计数器,并在方法末尾添加一个好的旧printf时,它变得更快了——gprof和手动测量都证实了这一点

我还不厌其烦地查看了G++在这两种情况下生成的汇编代码(有跟踪和无跟踪),没有重大变化(这是我最初的怀疑)——唯一的区别是为计数器分配了更多的堆栈字,增加了所述计数器,并准备printf,然后跳转到它

同样,这也适用于-O2和-O3。我在Ubuntu Maverick上使用GCC4.4.5和GPROF2.20.51


我想我的问题是:发生了什么?我做错了什么?我的测量和gprof都有问题吗?

花时间在printf中,你可能会在下次OpenGL调用中避免暂停。

花时间在printf中,你可能会在下次OpenGL调用中避免暂停。

没有更多信息,很难知道这里发生了什么,但这里有一些提示:

  • 你确定OpenGL调用是相同的吗?您可以使用一些工具来比较发出的呼叫。确保可能不同的操作顺序不会导致状态更改
  • 您是否尝试在运行时使用探查器?如果您有许多对象,在列表上循环时追逐指针的简单事实可能会导致缓存未命中
  • 您是否发现了CPU端或GPU端的特定瓶颈

以下是我自己对可能出现的问题的猜测。发送到GPU的调用需要一些时间才能完成:前面的代码通过混合CPU操作和GPU调用,使CPU和GPU并行工作;相反,新代码首先使CPU在GPU空闲时计算许多事情,然后在CPU无事可做时向GPU提供所有要完成的工作。

没有更多信息,很难知道这里发生了什么,但这里有一些提示:

  • 你确定OpenGL调用是相同的吗?您可以使用一些工具来比较发出的呼叫。确保可能不同的操作顺序不会导致状态更改
  • 您是否尝试在运行时使用探查器?如果您有许多对象,在列表上循环时追逐指针的简单事实可能会导致缓存未命中
  • 您是否发现了CPU端或GPU端的特定瓶颈

以下是我自己对可能出现的问题的猜测。发送到GPU的调用需要一些时间才能完成:前面的代码通过混合CPU操作和GPU调用,使CPU和GPU并行工作;相反,新代码首先让CPU在GPU空闲时计算很多事情,然后在CPU无事可做的情况下向GPU提供所有要完成的工作。

那么,分析说明了没有计数器的版本的哪些信息?顺便说一句,我推荐valgrind+callgrind作为探查器,kcachegrind作为可视化工具。在没有计数器的版本中,渲染功能的平均时间为0.02ms(总计)。在带有计数器的版本中,它不注册(总计0.00ms)。谢谢,我会尝试valgrind(但上次我尝试在同一个程序上使用它进行内存泄漏检查时,它与专有的nVidia驱动程序一起导致崩溃)。我也会尝试获得详细的配置文件,一直到源代码的各个行。如果配置文件如此简单,每个人都会放置随机计数器:对每个OpenGL调用进行优化只会测量向执行批处理添加操作所需的时间。但在您的案例中真正重要的是总渲染时间,即从帧的第一次OpenGL调用到完成glFinish调用的时间。我很确定,如果您比较两个版本的程序,那么在一个版本中调用OpenGL所需的额外时间将随着glFinish()在另一个版本中返回所需的更长时间而得到补偿。那么,分析说明了没有计数器的版本的什么呢?顺便说一句,我推荐valgrind+callgrind作为探查器,kcachegrind作为可视化工具。在没有计数器的版本中,渲染功能的平均时间为0.02ms(总计)。在带有计数器的版本中,它不注册(总计0.00ms)。谢谢,我会尝试valgrind(但上次我尝试在同一个程序上使用它进行内存泄漏检查时,它与专有的nVidia驱动程序一起导致崩溃)。我也会尝试获得详细的配置文件,一直到源代码的各个行。如果配置文件如此简单,每个人都会放置随机计数器:对每个OpenGL调用进行优化只会测量向执行批处理添加操作所需的时间。但在您的案例中真正重要的是总渲染时间,即从帧的第一次OpenGL调用到完成glFinish调用的时间。我很确定,如果比较两个版本的程序,在一个版本中调用OpenGL所需的额外时间将得到补偿,直到glFinish()在另一个版本中返回。我的下一个OpenGL调用是另一个完全不相关的函数,因此它不会对该特定函数产生影响。我可以尝试在两个测试函数的调用之间放置printf,它可能指向t