提高那段代码的执行速度

Posted

技术标签:

【中文标题】提高那段代码的执行速度【英文标题】:improving the speed of the execution of that piece of code 【发布时间】:2013-11-29 04:01:55 【问题描述】:

我有两种用于渲染网格的方法。第一个:

void Grid::openglRender()
  glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
  glBegin(GL_TRIANGLES);
  glColor3f(1.0f, 1.0f, 0.0f);
  Node* A, * B, * C, * D;
  for(size_t X=0 ; X<sizeX-1 ; X++)for(size_t Z=0 ; Z<sizeZ-1; Z++)
    A = &nodes[X*sizeZ+Z];
    B = &nodes[(X+1)*sizeZ+Z];
    C = &nodes[X*sizeZ+(Z+1)];
    D = &nodes[(X+1)*sizeZ+(Z+1)];
    glVertex3f(A->x, A->y, A->z);
    glVertex3f(B->x, B->y, B->z);
    glVertex3f(C->x, C->y, C->z);

    glVertex3f(B->x, B->y, B->z);
    glVertex3f(D->x, D->y, D->z);
    glVertex3f(C->x, C->y, C->z);
  
  glEnd();
;

第二个:

void Grid::openglRender()
  glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
  glBegin(GL_TRIANGLES);
  glColor3f(1.0f, 1.0f, 0.0f);
  for(size_t X=0 ; X<sizeX-1 ; X++)for(size_t Z=0 ; Z<sizeZ-1; Z++)
    glVertex3f(nodes[X*sizeZ+Z].x, nodes[X*sizeZ+Z].y, nodes[X*sizeZ+Z].z);
    glVertex3f(nodes[(X+1)*sizeZ+Z].x, nodes[(X+1)*sizeZ+Z].y, nodes[(X+1)*sizeZ+Z].z);
    glVertex3f(nodes[X*sizeZ+(Z+1)].x, nodes[X*sizeZ+(Z+1)].y, nodes[X*sizeZ+(Z+1)].z);

    glVertex3f(nodes[(X+1)*sizeZ+Z].x, nodes[(X+1)*sizeZ+Z].y, nodes[(X+1)*sizeZ+Z].z);
    glVertex3f(nodes[(X+1)*sizeZ+(Z+1)].x, nodes[(X+1)*sizeZ+(Z+1)].y, nodes[(X+1)*sizeZ+(Z+1)].z);
    glVertex3f(nodes[X*sizeZ+(Z+1)].x, nodes[X*sizeZ+(Z+1)].y, nodes[X*sizeZ+(Z+1)].z);
  
  glEnd();
;

对我来说,第一个在操作数量方面看起来更好,在glVertex3f 中,我只是使用指针来获取值。在第二种方法中,每次我都必须相乘并添加一些东西。

但在运行时我并没有真正感觉到有什么不同。所以当我说第一个更好时我是对的吗?或者也许我选择的编译器比我更清楚,如何获得最好的......

如果我在 for 循环之前声明 XZ 可能会更好一些,以避免特别是声明和销毁 sizeX 次 Z

另外我猜,最好的办法是创建一个列表(一次,存储的 ro 可以在每一帧重复使用),所有节点按顺序遍历以创建网格,而不是使用两个 for

【问题讨论】:

glVertex3f (...) far 的调用开销很有可能超过了您可以解决此问题的任何花哨的裤子指针算术技巧。像这样对即时模式进行微优化实际上没有任何意义,您应该切换到索引顶点数组并称之为更好地花费时间。但是,如果您坚持,如果您将glVertex3fv (... ) 加入其中以进行另一次微优化,您可以让这个噩梦持续更长时间。 @AndonM.Coleman 听起来不错,老实说我从来没有使用过顶点数组,所以当我写那个代码时我什至没有想到它。我在某本书中读到了一些关于它们的信息。明天我会在图书馆阅读更多相关内容 【参考方案1】:
A = &nodes[X*sizeZ+Z];
B = &nodes[(X+1)*sizeZ+Z];
C = &nodes[X*sizeZ+(Z+1)];
D = &nodes[(X+1)*sizeZ+(Z+1)];

可能

A = &nodes[X * sizeZ + Z];
B = A + sizeZ;
C = A + 1;
D = B + 1;

这不仅应该减少相当多的操作数量,而且还会使节点之间的关系更加明显。我不知道您的编译器有多聪明,以及它是否能够自己进行这种优化。但是,当替代方案更明确时,为什么必须这样做呢?

(这里是关于过早优化的强制性警告。如果您甚至没有注意到两者之间的区别,那么现在担心微优化还为时过早。)

【讨论】:

我喜欢我会重复使用这个【参考方案2】:

仅仅因为您优化了一段代码并不总是意味着您会看到更好的运行时性能。您如何衡量运行时性能?根据两个 for 循环中的迭代次数,您可能永远看不到差异,除非迭代次数足够高。 sizeX 和 sizeZ 的实际值是多少?

【讨论】:

其实我的目标是获得一些技巧来提高写作效率。我没有测量运行时间。 虽然确保编写干净高效的代码总是一件好事,但请注意不要落入“过早优化”的陷阱——这意味着要进行各种代码优化甚至不需要这样做。在某些情况下,它实际上会使代码对其他人变得不太清楚,具体取决于您进行了何种优化。 是的,我已经浪费了一些时间试图得到更好的东西。我总是试图提醒我年轻时一位老老师告诉我的话:«最好的是善的敌人»(翻译自法语)【参考方案3】:

这些调用已被弃用,这就是您的程序运行缓慢的原因之一。您应该改为研究 VBO 和着色器!

【讨论】:

我在看橙皮书(shaders)但是我不太明白shader应该写什么,什么应该用C++写,我知道shader使用GPU,所以我问自己如果所有与图形相关的东西都应该写在着色器中。 @bobthemightyspellcaster:不,只有用于动态计算的东西才属于着色器。有很多操作仍然需要在加载时只执行一次。我强烈建议您在进入着色器之前研究 OpenGL 管道的各个阶段 - 着色器实际上是在 GPU 上运行并计算管道某些阶段的输出的微型程序(例如,顶点变换阶段 = 顶点着色器,原始组装阶段 =几何着色器,光栅化阶段 = 片段着色器)。一旦你了解了管道的流程,着色器就更有意义了。 @bobthemightyspellcaster:查看this article了解更多详情。

以上是关于提高那段代码的执行速度的主要内容,如果未能解决你的问题,请参考以下文章

C程序的执行速度突然提高

只需几行代码,Python 执行速度就可以提高了30倍!

如何将 Python 数据管道的速度提高到 91 倍?

一行代码让你的python运行速度提高100倍

一行代码让 Python 的运行速度提高100倍

卧槽!一行代码让 Python 的运行速度提高100倍