C ++ metodi in linea con stesso if
-
25-09-2019 - |
Domanda
sto scrivendo gestore per OpenGL consistenza e sto pensando di sicurezza e prestazioni. Quale livello di ottimizzazione dovrebbe rimuovere segnato if?
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(...);
}
Soluzione
Nessuno.
storia triste, ma C ++ presuppone che se si chiama una funzione, allora questa funzione potrebbe produrre tutti i tipi di effetti collaterali, tra cui la modifica del valore di binded.ID (che la funzione sa in qualche modo a che fare)
ad eccezione di
Se si fare in modo che le funzioni si richiama hanno modo assolutamente legale per conoscere il vostro bindend.ID
, sia direttamente (facendo riferimento a esso) o indirettamente (perché qualcun altro prendere un puntatore di esso e lo passò in giro). Ecco un semplice esempio (supponendo che side_effect()
situata in un'unità diversa traduzione)
int side_effect();
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;
}
side_effect()
può utilizzare e cambiare k
legalmente dichiarando come un esterno. Nessuna chiamata di side_effect
può essere ottimizzato via.
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;
}
Non è possibile per side_effect
per l'accesso k
in maniera consentita, in quanto non è possibile statica di accesso in un'altra unità di traduzione. Pertanto il codice può essere ottimizzato per side_effect(); return 0
perché k non cambierà, finché side_effect () non frugare nella memoria. Quale sarebbe un comportamento indefinito, naturalmente.
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;
}
Il compilatore non ha modo di sapere, se snitch()
salva il suo argomento in un luogo dove side_effect()
può cambiare, quindi, nessuna chiamata a side_effect()
può essere eliminato.
È possibile ottenere la stessa situazione, se avete k
come variabile locale: Se c'è una possibilità che alcuni sconosciuti k
routine di accesso lattina in modo legale, allora il compilatore non può fare ottimizzazioni in base al valore di k <. / p>
PS: Fare k
const non aiuta, perché è legale per lanciare un const distanza. const-ness non può essere usato come un suggerimento di ottimizzazione.
Altri suggerimenti
Questo dipenderà dal compilatore e la soluzione migliore è quella di prova -. Compilazione e ispezionare il codice macchina emessa
Nessun livello di ottimizzazione può (giustamente) rimuovere questi test. Essi potrebbero essere rimossi solo se entrambi gli argomenti erano costanti in fase di compilazione, e nessuno di questi sono, o se il compilatore può dimostrare che non cambieranno valore tra le prove.
Dal binded
è statico, il compilatore non può sapere che le chiamate alle funzioni GL non alterarlo.