Встроенные методы C ++ с такими же операторами if - PullRequest
3 голосов
/ 04 августа 2010

Я пишу обработчик для текстуры OpenGL, и я думаю о безопасности и производительности.Какой уровень оптимизации должен удалить помеченные операторы 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(...);
}

Ответы [ 3 ]

4 голосов
/ 04 августа 2010

Нет.

Грустная история, но C ++ предполагает, что если вы вызываете функцию, то эта функция может вызывать всевозможные побочные эффекты, включая изменение значения binded.ID (что функция каким-то образом знает)

За исключением

Если вы убедитесь, что вызываемые вами функции не имеют абсолютно никакого законного способа узнать о вашем bindend.ID, либопрямо (путем ссылки на него) или косвенно (потому что кто-то другой взял указатель на него и передал его).Вот простой пример (при условии, что side_effect() находится в другой единице перевода)

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() может использовать и изменять k на законных основаниях, объявляя его внешним.Нельзя оптимизировать вызов side_effect.

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;
}

Для side_effect невозможно получить доступ к k разрешенным способом, потому что вы не можете получить доступ к статике в другой единице перевода.Следовательно, код можно оптимизировать до side_effect(); return 0, потому что k не изменится, пока side_effect () не копается в памяти.Конечно, это было бы неопределенным поведением.

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_effect() может его изменить, поэтому нет вызова side_effect()можно исключить.

Вы получите ту же ситуацию, если у вас есть k в качестве локальной переменной: если есть вероятность, что какая-то неизвестная подпрограмма может получить доступ к k легальным способом, то компилятор можетне выполнять оптимизацию на основе значения k.

PS: Создание k const не помогает, поскольку законно отбрасывать const.Константность не может быть использована в качестве подсказки по оптимизации.

2 голосов
/ 04 августа 2010

Никакой уровень оптимизации не может (правильно) удалить эти тесты.Их можно удалить только в том случае, если оба аргумента были константами времени компиляции, и ни один из них не является таковыми, или если компилятор может доказать, что они не изменят значение между тестами.

Поскольку binded является статическим, компилятор не может знать, что вызовы функций GL не изменят его.

2 голосов
/ 04 августа 2010

Это будет зависеть от компилятора, и вам лучше всего протестировать - скомпилировать и проверить выданный машинный код.

...