C++ C++;具有相同if语句的内联方法
我正在为OpenGL纹理编写处理程序,我正在考虑安全性和性能。哪一级的优化应该删除标记的if语句C++ C++;具有相同if语句的内联方法,c++,compiler-optimization,inline-method,C++,Compiler Optimization,Inline Method,我正在为OpenGL纹理编写处理程序,我正在考虑安全性和性能。哪一级的优化应该删除标记的if语句 struct Texture2D { GLuint ID; inline Texture2D(): ID(0) {}; inline explicit Texture2D(GLuint id): ID(id) {}; ~Texture2D(); void GenTexture(bool regen = false); void DeleteTex
struct Texture2D {
GLuint ID;
inline Texture2D(): ID(0) {};
inline explicit Texture2D(GLuint id): ID(id) {};
~Texture2D();
void GenTexture(bool regen = false);
void DeleteTexture();
void BindTexture();
void Parameterf( GLenum pname, GLfloat param );
void Parameteri( GLenum pname, GLint param );
void glTexParameterfv( GLenum target, GLenum pname, const GLfloat *params );
void glTexParameteriv( GLenum target, GLenum pname, const GLint *params );
static Texture2D binded;
};
inline void Texture2D::GenTexture(bool regen) {
if(ID){
if(regen)
DeleteTexture();
else
return;
}
glGenTextures(1,&ID);
}
inline void Texture2D::DeleteTexture() {
glDeleteTextures(1,&ID);
ID = 0;
}
inline void Texture2D::BindTexture() {
glBindTexture(GL_TEXTURE_2D, ID);
binded.ID = ID;
}
inline void Texture2D::Parameterf( GLenum pname, GLfloat param ){
if(binded.ID == ID) // THIS
BindTexture(); // THIS
glTexParameterf(GL_TEXTURE_2D,pname,param);
}
inline void Texture2D::Parameteri( GLenum pname, GLint param ){
if(binded.ID == ID) // THIS
BindTexture(); // THIS
glTexParameterf(GL_TEXTURE_2D,pname,param);
}
inline Texture2D::~Texture2D() {
DeleteTexture();
}
// in this function
void loadTexture(...) {
Texture2D t;
t.GenTexture();
t.BindTexture();
// if statements in next functions
t.Parameterf(...);
t.Parameterf(...);
t.Parameterf(...);
t.Parameterf(...);
t.Parameterf(...);
}
这取决于编译器,您最好的选择是测试-编译并检查发出的机器代码。任何优化级别都无法(正确)删除这些测试。只有当两个参数都是编译时常量,而这两个参数都不是,或者编译器可以证明它们不会在测试之间更改值时,才能删除它们 由于绑定的
是静态的,编译器无法知道对GL函数的调用不会改变它。无。
悲伤故事,但C++假定如果调用函数,则此函数可能产生各种副作用,包括更改BIDED.ID的值(函数不知何故要做)
除
如果您确保您调用的函数绝对没有合法的方式来了解您的bindend.ID
,可以直接(通过引用它)或间接(因为其他人拿着它的指针并传递它)。下面是一个简单的示例(假设副作用()
位于不同的翻译单元中)
side_effect()
可以合法地使用和更改k
,方法是将其声明为外部。不能优化掉副作用的调用
int side_effect();
static int k=1;
int main()
{
side_effect();
if (k!=0) return 0;
side_effect();
if (k!=0) return 0;
side_effect();
if (k!=0) return 0;
}
副作用
无法以允许的方式访问k
,因为您无法访问其他翻译单元中的静态数据。因此,代码可以优化为副作用();返回0
,因为只要内存中没有出现副作用(),k就不会改变。这当然是未定义的行为
int side_effect();
void snitch(int*);
static int k=1;
int main()
{
snitch(&k); // !!!
side_effect();
if (k!=0) return 0;
side_effect();
if (k!=0) return 0;
side_effect();
if (k!=0) return 0;
}
编译器无法知道snitch()
是否将其参数保存在side\u effect()
可以更改它的位置,因此无法消除对side\u effect()
的调用
如果将k
作为局部变量,则会出现相同的情况:如果某个未知例程可能以合法方式访问k
,则编译器无法基于k的值进行优化
PS:生成k
const没有帮助,因为丢弃const是合法的。常量不能用作优化提示。为什么任何级别的优化都应该这样做?这些不是吗=代码>?(还有,bind的过去分词是bind)您是否打算将这些测试设置为=代码>?编译器将很难证明在opengl调用期间静态变量没有被修改,因此一般来说,它无法消除条件测试。@Neil;它们是内联的,所以只需要第一个。@行我不知道内联与它有什么关系。不完全正确,如果它们是stackframe的本地对象,也可以删除它,但它们是全局的+不管怎样,它都不应该依赖于编译器,因为正如路德·布利塞特所解释的那样。变量可以在GL调用期间更改。实际上,最好的方法是只编写清晰的代码,并且只有在确定这些语句是瓶颈时才进行优化。但是,测试是确定编译器功能的唯一方法。进行链接时代码生成的现代编译器可能有信息知道k是否会因副作用而改变。然而,在C++中证明它是安全的还是非常困难的,所以我不期望它,并且同意实践中的答案。
int side_effect();
void snitch(int*);
static int k=1;
int main()
{
snitch(&k); // !!!
side_effect();
if (k!=0) return 0;
side_effect();
if (k!=0) return 0;
side_effect();
if (k!=0) return 0;
}