【问题标题】:Speeding up an IO bound OpenGL application加速 IO 绑定的 OpenGL 应用程序
【发布时间】:2011-03-24 11:01:30
【问题描述】:

我最近一直在研究一个点云播放器,它应该能够理想地可视化来自激光雷达捕获的地形数据点,并以大约 30 fps 的速度依次显示它们。然而,我似乎遇到了 PCI-e IO 的问题。

我需要为每一帧加载一个存储在内存中的大点云,然后根据高度计算颜色图(我使用类似于 matlab 的喷射图),然后将数据传输到 GPU。这适用于点数 每秒大约 1.34 GB )

我的渲染代码现在看起来像这样:

glPointSize(ptSize);
glEnableClientState(GL_VERTEX_ARRAY);
if(colorflag) {
    glEnableClientState(GL_COLOR_ARRAY);
} else {
    glDisableClientState(GL_COLOR_ARRAY);
    glColor3f(1,1,1);
}
glBindBuffer(GL_ARRAY_BUFFER, vbobj[VERT_OBJ]);
glBufferData(GL_ARRAY_BUFFER, cloudSize, vertData, GL_STREAM_DRAW);
glVertexPointer(3, GL_FLOAT, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, vbobj[COLOR_OBJ]);
glBufferData(GL_ARRAY_BUFFER, cloudSize, colorData, GL_STREAM_DRAW);
glColorPointer(3, GL_FLOAT, 0, 0);
glDrawArrays(GL_POINTS, 0, numPoints);
glDisableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, 0);

vertData 和 colorData 的指针每帧都会改变。

我希望能够以每秒至少 30 帧的速度播放,即使稍后使用可能达到每帧 700 万点的大型点云。这甚至可能吗?或者也许将它们网格化并构建一个高度图并以某种方式显示它会更容易?我对 3-D 编程还是很陌生,所以任何建议都将不胜感激。

【问题讨论】:

  • 你真的需要每帧发送所有数据吗?你不能在需要的时候更新高度,只在 GPU 上发送这个,然后在着色器中计算颜色吗?在 GPU 上无法完成的 CPU 更新有哪些?
  • 我的问题是点云都是预先记录的,所以我只需要显示它们。我并没有真正做任何计算,所以我不能只更新东西:\
  • 我和@Calvin1602有同样的想法。我不知道这是否有帮助:stackoverflow.com/questions/371898/… 但它的作用是比较新旧东西,找出差异,并在带宽存在问题时使用它们来更新“远程”数据结构。

标签: performance opengl optimization 3d lidar


【解决方案1】:

如果可以,请使用 1D 纹理实现颜色映射。您只需要 1 个纹理坐标而不是 3 种颜色,它也会使顶点 128 位对齐。

编辑:您只需要从颜色图创建纹理并使用 glTexCoordPointer 而不是 glColorPointer (当然,在 [0, 1] 范围内更改纹理坐标的顶点颜色值)。这是线性插值的 6 texel 颜色图:

// Create texture
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_1D, texture);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

// Load textureData
GLubyte colorData[] = {
    0xff, 0x00, 0x00,
    0xff, 0xff, 0x00,
    0x00, 0xff, 0x00,
    0x00, 0xff, 0xff,
    0x00, 0x00, 0xff,
    0xff, 0x00, 0xff
};
glTexImage1D(GL_TEXTURE_1D, 0, GL_RGB, 6, 0, GL_RGB, GL_UNSIGNED_BYTE, colorData);
glEnable(GL_TEXTURE_1D);

【讨论】:

  • 感谢您的回答。我不太确定如何使用 1D 纹理作为颜色图,有什么可以阅读的吗?在此先感谢(对不起,我有点像opengl noob :D)
【解决方案2】:

我对opengl一无所知,但是数据压缩在这里不是一种自然的解决方法吗? 不支持整数类型或 16 位浮点数吗? 还有其他颜色表示不是每点 3 个浮点数吗?

【讨论】:

  • 数据压缩听起来不错,但不知道能不能用opengl在GPU端解压。我会尝试索引颜色,谢谢
  • 好吧,即使是真正的压缩也可以使用 GPGPU,但我只是说 glVertexPointer 显然支持 GL_SHORT 和 glColorPointer - GL_BYTE。你真的需要浮点精度吗?虽然索引颜色当然更好。
【解决方案3】:

如果您愿意处理延迟,您可以加倍(或更多!)缓冲 VBO,将几何图形传输到一个缓冲区,同时从另一个缓冲区渲染:

while(true)
{
    draw_vbo( cur_vbo_id );
    generate_new_geometry();
    load_vbo( nxt_vbo_id );
    swap( cur_vbo_id, nxt_vbo_id );
}

编辑:您也可以尝试interleaving 您的顶点,而不是每个组件使用一个 VBO。

【讨论】:

  • 延迟不是问题,但我不确定我是否看到双缓冲 VBO 将如何帮助加快传输时间。每个 VBO 是否有一些开销?谢谢,我明天会尝试交错
【解决方案4】:

你说它是 I/O 绑定的。这意味着您已经对其进行了概要分析,并看到它花费 50% 或更多的时间等待 I/O。

如果是这样,那就是你必须关注的,而不是图形。

如果不是,那么其他一些答案对我来说听起来不错。无论如何,个人资料,不要猜测This is the method I use.

【讨论】:

  • I/O bound 指的是 GPU 的 PCI-express 总线上的 I/O,而不是 HDD 或网络。但你仍然是对的。
  • 我很确定它是 IO 绑定的,因为我只是使用反复播放的同一帧进行测试。如果我只是注释掉 memcpy ,它的速度最高可达 60fps :\.
  • @Xzhsh wtf ?我不明白了。你说的是哪个 memcpy?
  • Err 对不起,我的意思是 bufferdata 调用。我所做的测试是在初始化函数中从内存中加载相同的帧数据,然后在每个并条帧中不断加载相同的帧数据。如果我只加载一次帧数据,它可以达到 100 fps,但如果我每帧都加载数据(当我获得更多数据时需要这样做),fps 会下降到 10 左右。
  • @Xzhsh:如果您还没有听说过这种技术,我并不感到惊讶,因为您在 gprof 的家中。无论如何,这里有更多关于这个主题的内容:stackoverflow.com/questions/1777556/alternatives-to-gprof/…
【解决方案5】:

一些提示:

  • 在显卡上存储尽可能多的数据并仅加载真正需要的数据(非常明显)
  • 在树中使用 lod 级别(kd 或八叉树)并尽可能多地预先计算
  • 磁盘压缩对于克服 io 瓶颈也很有用

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多