Performance OpenGL计算着色器比';相同';OpenCL内核。为什么?
我有一个小游戏,我想移植到Android上。PC版本最初使用(现在仍然可以使用)OpenCL进行碰撞检测,在cpu实现上显示了230x(!)的速度。我想将并行编程转移到OpenGL,使用计算着色器剪切ocl,将其全部保留在ogl中。我有我的第一个ogl计算着色器使用的代码在功能上与ocl版本相同,但它比ocl版本慢14倍 我在这里读过一些关于ogl计算着色器性能的帖子,它们通常都是关于访问纹理的。我没有纹理,只有两个SSBO;一个用于输入,一个用于输出 该任务是一个nbody问题,代码(蛮力)检查所有内容与其他内容。程序可以有数千个点(每次迭代都可以添加和删除任意数量的点)。我希望有尽可能多的并发点 2000点的时间是:Performance OpenGL计算着色器比';相同';OpenCL内核。为什么?,performance,opengl,opencl,compute-shader,Performance,Opengl,Opencl,Compute Shader,我有一个小游戏,我想移植到Android上。PC版本最初使用(现在仍然可以使用)OpenCL进行碰撞检测,在cpu实现上显示了230x(!)的速度。我想将并行编程转移到OpenGL,使用计算着色器剪切ocl,将其全部保留在ogl中。我有我的第一个ogl计算着色器使用的代码在功能上与ocl版本相同,但它比ocl版本慢14倍 我在这里读过一些关于ogl计算着色器性能的帖子,它们通常都是关于访问纹理的。我没有纹理,只有两个SSBO;一个用于输入,一个用于输出 该任务是一个nbody问题,代码(蛮力)检
- cpu:713.0毫秒
- ogl计算着色器:44.0毫秒
- ocl:3.1毫秒
for (Point * p1: points) {
for (Point * p2: points) {
// perform collision detection
// calculate and accumulate any repulsive force on p1
}
}
并行程序的目的是使顶部循环变平。所以这是一个幼稚的实现,但现在对我来说还不错如果ocl的速度足以达到230倍,那么ogl应该不会落后太多,对吧
< > C++代码:
void Render::compute (int num_stuff, PointCSData * data, PointCSData_Out *& data_out) {
// data IN
glBindBuffer (GL_SHADER_STORAGE_BUFFER, csbo);
glBufferData (GL_SHADER_STORAGE_BUFFER, num_stuff * sizeof(PointCSData), data, GL_DYNAMIC_COPY);
glUnmapBuffer (GL_SHADER_STORAGE_BUFFER);
// data OUT - prep space
glBindBuffer (GL_SHADER_STORAGE_BUFFER, csbo_out);
glBufferData (GL_SHADER_STORAGE_BUFFER, num_stuff * sizeof(PointCSData_Out), NULL, GL_DYNAMIC_COPY);
glUnmapBuffer (GL_SHADER_STORAGE_BUFFER);
glBindBufferBase (GL_SHADER_STORAGE_BUFFER, 0, csbo);
glBindBufferBase (GL_SHADER_STORAGE_BUFFER, 1, csbo_out);
glUseProgram (computeProgram);
glDispatchCompute (num_stuff / 32, 32, 1);
glMemoryBarrier (GL_ALL_BARRIER_BITS);
glBindBuffer (GL_SHADER_STORAGE_BUFFER, csbo_out);
GLuint bufMask = GL_MAP_READ_BIT;
data_out = (PointCSData_Out *) glMapBufferRange (GL_SHADER_STORAGE_BUFFER, 0, num_stuff * sizeof(PointCSData_Out), bufMask);
glUnmapBuffer (GL_SHADER_STORAGE_BUFFER);
glUseProgram (0);
}
着色器:
#version 430
struct PointData {
int is_fixed;
float posx, posy;
int thingpntr;
float friction; // not used
float rigidity;
vec2 vel; // not used
};
struct PointData_Out {
vec2 acc;
vec2 accrig;
};
layout (std430, binding=0) buffer cs_data {
PointData data [ ];
};
layout (std430, binding=1) buffer cs_data_out {
PointData_Out data_out [ ];
};
layout (local_size_x = 32, local_size_y = 1, local_size_z = 1) in;
void main () {
float k = 500.0; // Hookes_K
float d = 8.0; // collision_d
uint n = gl_NumWorkGroups.x * gl_NumWorkGroups.y; // num stuff
uint gid = gl_GlobalInvocationID.x;
if (data [gid].thingpntr == -1 // skip if padding point
|| data [gid].is_fixed == 1) // skip if fixed point
return;
float rig = data [gid].rigidity;
vec2 p1_pos = vec2 (data [gid].posx, data [gid].posy);
vec2 p2_pos;
vec2 acc; // accumulators
vec2 accrig;
float f, h;
vec2 dif;
vec2 norm;
vec2 F;
for (uint i=0; i<n; i++) {
if (data [gid].thingpntr == data [i].thingpntr // skip if of same thing
|| data [i].thingpntr == -1 // skip if padding point
|| i == gid) // skip if self
continue;
p2_pos = vec2 (data [i].posx, data [i].posy);
h = distance (p2_pos, p1_pos);
if (h > d || h == 0.0) continue;
f = k * (h - d);
dif = p2_pos - p1_pos;
norm = dif / h;
F = norm * f;
acc += F * (1.0 - rig);
accrig += F * rig;
}
data_out [gid].acc = acc;
data_out [gid].accrig = accrig;
}
#版本430
结构点数据{
int是固定的;
浮动posx,posy;
国际贸易永久正常贸易关系;
浮动摩擦;//未使用
浮动刚度;
vec2 vel;//未使用
};
结构点数据输出{
vec2 acc;
vec2-accrig;
};
布局(std430,绑定=0)缓冲区cs\U数据{
点数据[];
};
布局(std430,绑定=1)缓冲区cs\U数据\U输出{
点数据输出数据输出[];
};
布局(本地大小x=32,本地大小y=1,本地大小z=1)在中;
空干管(){
浮动k=500.0;//虎克
float d=8.0;//冲突\u d
uint n=gl_NumWorkGroups.x*gl_NumWorkGroups.y;//num stuff
uint gid=gl_globalinovationid.x;
if(数据[gid].thingpntr==-1//跳过填充点
||数据[gid]。是固定的==1)//如果是固定点,则跳过
返回;
浮动钻机=数据[gid]。刚度;
vec2 p1_pos=vec2(数据[gid].posx,数据[gid].posy);
vec2 p2_位置;
vec2 acc;//累加器
vec2-accrig;
浮点数f,h;
vec2-dif;
vec2范数;
vec2f;
对于(uint i=0;id | h==0.0)继续;
f=k*(h-d);
dif=p2_位置-p1_位置;
norm=dif/h;
F=标准*F;
acc+=F*(1.0-钻机);
accrig+=F*钻机;
}
数据输出[gid].acc=acc;
数据输出[gid]。accrig=accrig;
}
调用glBufferData()和glMapBufferRange()时,是否可以使用访问位字段
同样,是什么使得ogl计算着色器版本的运行速度比功能完全相同的ocl verion慢得多?与pc相比,android的opengl资源会比opencl少吗?例如减少14倍?现在都在同一台电脑上。我“我计划移植到Android,但还没有。我想这就是我设置计算着色器的方式,但不知道。@pawel-为什么在着色器中循环
num\u stuff
次?我的意思是如果在P1
你发现P1
与P100
相交。那么,当您在P100时,为什么还要再次检查它呢?因为对于p1,我找到(p1,P100)并将力施加到p1上,对于P100,我找到力(P100,p1)并将力施加到P100上。如果我在p1的两个方向上施加力(方向相同但相反),那么当我到达p100时,我必须以某种方式“知道”p100已经被p1访问过。但因为这一切都是并行的,没有什么可以保证在“做”其他任何事情之前完成,所以我独立地更新每个点。这有点离题了,因为ocl中的相同方法(好或坏)快了14倍——这是重点,也是问题所在。关于你删除的问题,你可能会发现一个讨论平台会是一个更好的家。你试过Reddit吗?IMO,那里有一些很好的开发论坛,他们可能欢迎尝试一种新的图像格式。