Opengl 对GLSL着色器进行基准测试,以比较替代实现的速度

Opengl 对GLSL着色器进行基准测试,以比较替代实现的速度,opengl,glsl,microbenchmark,Opengl,Glsl,Microbenchmark,我想使用OpenGL和GLSL着色器绘制二维函数z=f(x,y)。我想使用colormap将函数的值映射到颜色,但有些颜色贴图是使用HSL或HSV颜色空间表示的(例如色调贴图) 您可以在GLSL中找到(这里和其他地方)不同的hsv2rgb()替代实现 如何对这些着色器(那些函数)进行基准测试,以找出哪一个最快?实现所有您想要尝试的替代方案,并应用通常的基准建议: 重复单个基准测试足够多的次数,使时间为秒(较少的测试会受到太多噪音的影响) 在要在其中运行的环境中重复基准测试 试着让设置尽可能接近

我想使用OpenGL和GLSL着色器绘制二维函数
z=f(x,y)
。我想使用colormap将函数的值映射到颜色,但有些颜色贴图是使用HSL或HSV颜色空间表示的(例如色调贴图)

您可以在GLSL中找到(这里和其他地方)不同的
hsv2rgb()
替代实现


如何对这些着色器(那些函数)进行基准测试,以找出哪一个最快?

实现所有您想要尝试的替代方案,并应用通常的基准建议:

  • 重复单个基准测试足够多的次数,使时间为秒(较少的测试会受到太多噪音的影响)
  • 在要在其中运行的环境中重复基准测试
  • 试着让设置尽可能接近现实(相同的背景流程等)
  • 重复基准运行几次,忽略异常值
  • 将运行之间的算法/测试顺序随机化
  • 确保对正在测试的节禁用缓存(如果适用)
既然你包括OpenGL解决方案,那么你也应该考虑是否要对数据传输进行计数。确保刷新管道(opengl会取消某些调用,但刷新将等待它们实际完成)


如果运行时间太近,您可以说它们大致相同,或者增加数据大小/重复次数以使差异更加突出。

对于已实现的颜色贴图,我建议使用纹理

类似于256x1纹理的东西(ES中不支持1D纹理,如果这对您很重要的话),然后从f(x,y)的浮点结果中,将其用作纹理坐标


如果你有很多点要绘制,这将比每次在glsl中计算要快,而且GPU擅长纹理:)

你需要能够首先测量GL渲染的时间。我在C++中这样做:

// few variables
OpenGLtime    tim;
double draw_time;

// measurement
tim.tbeg();
// here render your stuff using binded shader
tim.tend();
draw_time=tim.time(); // time the render took in [s] just output it somewhere so you can see it
//------------------------------------------------------------------------------
类OpenGLtime
{
公众:
无符号整数id[2];
OpenGLtime();
OpenGLtime(OpenGLtime&a);
~OpenGLtime();
OpenGLtime*运算符=(常量OpenGLtime*a);
//OpenGLtime*运算符=(const OpenGLtime&a);
void _init();
void tbeg();//标记测量的开始时间
void tend();//标记度量值的结束时间
double time();//等待测量和返回时间[s]
};
//------------------------------------------------------------------------------
OpenGLtime::OpenGLtime()
{
id[0]=0;
id[1]=0;
}
//------------------------------------------------------------------------------
OpenGLtime::OpenGLtime(OpenGLtime&a)
{
id[0]=0;
id[1]=0;
}
//------------------------------------------------------------------------------
OpenGLtime::~OpenGLtime()
{
}
//------------------------------------------------------------------------------
OpenGLtime*OpenGLtime::operator=(常量OpenGLtime*a)
{
*这=*a;
归还这个;
}
//------------------------------------------------------------------------------
void OpenGLtime::_init()
{
//生成两个查询
glgenquerys(2,id);
}
//------------------------------------------------------------------------------
void OpenGLtime::tbeg()
{
如果(!id[0])_init();
//发出查询
glQueryCounter(id[0],GLU时间戳);
}
//------------------------------------------------------------------------------
void OpenGLtime::tend()
{
如果(!id[0])_init();
//发出查询
glQueryCounter(id[1],GLU时间戳);
}
//------------------------------------------------------------------------------
double OpenGLtime::time()
{
如果(!id[0]){u init();返回0.0;}
双dt;
GLuint64 t0,t1;
国际站;
//等待结果出来
对于(_-stop=0;!_-stop;Sleep(1))glGetQueryObjectiv(id[0],GL\u查询结果可用,&\u-stop);
对于(_-stop=0;!_-stop;Sleep(1))glGetQueryObjectiv(id[1],GL\u查询结果可用,&\u-stop);
//获取查询结果
GLGETQUERYOBJECTAI64V(id[0],GLU查询结果,&t0);
glGetQueryObjectai64v(id[1],GL\u查询结果,&t1);
dt=double(t1)-double(t0);dt*=0.000000001;
返回dt;
}
//------------------------------------------------------------------------------
现在您可以这样使用它:

// few variables
OpenGLtime    tim;
double draw_time;

// measurement
tim.tbeg();
// here render your stuff using binded shader
tim.tend();
draw_time=tim.time(); // time the render took in [s] just output it somewhere so you can see it
现在,您应该创建渲染内容。并且可以直接比较运行时


正如您所看到的,您将测量整个渲染过程/调用的时间,而不是GLSL代码的一部分。所以你必须考虑到这一点。我不知道如何直接测量GLSL代码的一部分。相反,你可以不用问题中的部分来测量时间,然后用它。。。减少时间,但编译器优化可能会把它搞砸。

(是的,我知道这并不能真正回答问题,但如果你想进行基准测试,我想你希望它速度快,而且我认为这个替代方案将比任何GLSL实现都快)好主意。这还有一个额外的优点,就是我可以使用相同的纹理向用户显示彩色贴图(用它制作一个窄矩形的纹理)。是的,这正是我在我的应用程序中所做的:),你也可以拥有一个包含多个颜色贴图的纹理,只需使用统一的颜色选择活动的颜色贴图即可。好吧,使用colormap函数,您可以使用
子例程
s和
子例程统一
来选择colormap函数。