【发布时间】:2016-08-14 10:22:13
【问题描述】:
条件
我使用OpenGL 3 和PyOpenGL。
我有大约 50,000 (53'490) 个顶点,每个顶点都有 199 个vec3 属性来确定它们的位移。无法将这些数据存储为常规顶点属性,因此我使用纹理。
问题是:非并行化的C 函数计算顶点位移的速度与GLSL 一样快,在某些情况下甚至更快。我检查过:问题是纹理读取,我不明白如何优化它。
我编写了两个不同的着色器。一个在 ~0.09s 内计算新模型,另一个在 ~0.12s 内计算(包括属性分配,这两种情况都相同)。
代码
两个着色器都以
开头#version 300 es
in vec3 vin_position;
out vec4 vin_pos;
uniform mat4 rotation_matrix;
uniform float coefficients[199];
uniform sampler2D principal_components;
更快的是
void main(void) {
int c_pos = gl_VertexID;
int texture_size = 8192;
ivec2 texPos = ivec2(c_pos % texture_size, c_pos / texture_size);
vec4 tmp = vec4(0.0);
for (int i = 0; i < 199; i++) {
tmp += texelFetch(principal_components, texPos, 0) * coefficients[i];
c_pos += 53490;
texPos = ivec2(c_pos % texture_size, c_pos / texture_size);
}
gl_Position = rotation_matrix
* vec4(vin_position + tmp.xyz, 246006.0);
vin_pos = gl_Position;
}
较慢的
void main(void) {
int texture_size = 8192;
int columns = texture_size - texture_size % 199;
int c_pos = gl_VertexID * 199;
ivec2 texPos = ivec2(c_pos % columns, c_pos / columns);
vec4 tmp = vec3(0.0);
for (int i = 0; i < 199; i++) {
tmp += texelFetch(principal_components, texPos, 0) * coefficients[i];
texPos.x++;
}
gl_Position = rotation_matrix
* vec4(vin_position + tmp.xyz, 246006.0);
vin_pos = gl_Position;
}
它们之间的主要区别:
- 在第一种情况下,顶点的属性以下列方式存储:
- 所有顶点的第一个属性
- 所有顶点的第二个属性
- ...
- 所有顶点的最后一个属性
- 在第二种情况下,顶点的属性以另一种方式存储:
- 第一个顶点的所有属性
- 第二个顶点的所有属性
- ...
- 最后一个顶点的所有属性
- 同样在第二个示例中,数据是对齐的,以便每个顶点的所有属性仅存储在一行中。这意味着如果我知道某个顶点的第一个属性的行和列,我只需要增加纹理坐标的
x分量
我想,对齐的数据会被更快地访问。
问题
- 为什么不能更快地访问数据?
- 如何提高它的性能?
- 是否可以将纹理块与顶点链接?
- 是否有关于数据对齐的建议,以及关于 GPU(Intel HD、nVidia GeForce)中缓存的良好相关文章?
注意事项
-
coefficients数组逐帧变化,否则没问题:我可以预先计算模型并且很高兴
【问题讨论】:
-
性能差异可能与着色器的执行方式有关。通常一堆着色器并行执行相同的命令。当所有第一个属性彼此靠近存储时,并行着色器读取相邻纹素的机会很高,这将更快。
-
我在您的代码中看到了很多预计算的潜力。
c_pos的演变仅取决于 VertexID。coefficients和deviations的乘法也可以很简单地合并。而且因为迭代总是通过相同的 199 个元素,甚至可以与principal_componentsLUT 合并。这意味着您可以保存 199 次纹理查找和 2×199 次乘法。这……很多。 -
@BDL 是的,我也想过这个问题。我将尝试不同的对齐方式,但我猜测存在一些关于更佳间隔的建议,或者我可以将纹理块分配给特定顶点。
-
@datenwolf
coefficients参数在每一帧中都不同,所以我唯一能做的就是预先计算coefficients和deviations的乘积。我已经这样做了,现在我有 ~0.09s vs ~0.12s,所以差异仍然存在。谢谢,我会更改有问题的代码! -
coefficients中有多少是零或可以忽略不计?
标签: performance opengl glsl textures