GLES 为 float 计算着色器原子操作
GLES compute shader atomic operations for float
我正在使用计算机着色器获取总和值(类型为浮点数),如下所示:
#version 320 es
layout(local_size_x = 640,local_size_y=480,local_size_z=1)
layout(binding = 0) buffer OutputData{
float sum[];
}output;
uniform sampler2D texture_1;
void main()
{
vec2 texcoord(float(gl_LocalInvocationIndex.x)/640.0f,float(gl_LocalInvocationIndex.y)/480.0f);
float val = textureLod(texture_1,texcoord,0.0).r;
//where need synchronize
sum[0] = sum[0]+val;
//Here i want to get the sum of all val in texture_1 first channal
}
我知道有像 atomicAdd() 这样的原子操作,但不支持 float 参数,而 barrier() 似乎不能解决我的问题。
也许我可以将浮点数编码为整数,或者有一些简单的方法可以解决我的问题吗?
Atomics 在性能方面通常很差,尤其是在大量线程并行访问激烈竞争的情况下,因此我不建议将它们用于此用例。
要在这里保持并行性,您确实需要某种多遍缩减策略。伪代码,像这样:
array_size = N
data = input_array
while array_size > 1:
spawn pass with M = array_size/2 threads.
thread M: out[M] = data[2*M] + data[2*M+1]
array_size = M
data = out
这是一个简单的 2:1 缩减,因此性能为 O(log2(N)),但您可以在每次通过时进行更多缩减,以减少中间存储的内存带宽。对于使用纹理作为输入的 GPU,4:1 非常好(您可以使用 textureGather 甚至简单的线性过滤器在单个纹理操作中加载多个样本)。
我正在使用计算机着色器获取总和值(类型为浮点数),如下所示:
#version 320 es
layout(local_size_x = 640,local_size_y=480,local_size_z=1)
layout(binding = 0) buffer OutputData{
float sum[];
}output;
uniform sampler2D texture_1;
void main()
{
vec2 texcoord(float(gl_LocalInvocationIndex.x)/640.0f,float(gl_LocalInvocationIndex.y)/480.0f);
float val = textureLod(texture_1,texcoord,0.0).r;
//where need synchronize
sum[0] = sum[0]+val;
//Here i want to get the sum of all val in texture_1 first channal
}
我知道有像 atomicAdd() 这样的原子操作,但不支持 float 参数,而 barrier() 似乎不能解决我的问题。 也许我可以将浮点数编码为整数,或者有一些简单的方法可以解决我的问题吗?
Atomics 在性能方面通常很差,尤其是在大量线程并行访问激烈竞争的情况下,因此我不建议将它们用于此用例。
要在这里保持并行性,您确实需要某种多遍缩减策略。伪代码,像这样:
array_size = N
data = input_array
while array_size > 1:
spawn pass with M = array_size/2 threads.
thread M: out[M] = data[2*M] + data[2*M+1]
array_size = M
data = out
这是一个简单的 2:1 缩减,因此性能为 O(log2(N)),但您可以在每次通过时进行更多缩减,以减少中间存储的内存带宽。对于使用纹理作为输入的 GPU,4:1 非常好(您可以使用 textureGather 甚至简单的线性过滤器在单个纹理操作中加载多个样本)。