Как помочь компилятору устранить циклы и массивы? - PullRequest
0 голосов
/ 14 июля 2010

Допустим, вы пишете 3D-рендерер с поддержкой мультитекстурирования, где количество текстурных блоков настраивается через постоянную времени компиляции.В отличие от жесткого кодирования отдельного текстурного блока, ваш код теперь должен обращаться к связанным с текстурами параметрам через массивы и обрабатывать их через циклы.

Предполагая, что в современном компиляторе C ++ есть какие-то практики, которые вы должны выполнитьдля того, чтобы компилятор генерировал эквивалентный код для жестко закодированных единичных текстурных блоков, когда число текстурных блоков установлено в один?

Ответы [ 2 ]

1 голос
/ 14 июля 2010

Что не так с циклами и массивами?

Развертывание циклов имеет недостаток: он делает код больше. Чем больше код, тем больше обращений к памяти для извлечения кода, а поскольку доступ к памяти медленный, ваш код может оказаться медленнее. Кроме того, процессор Intel предварительно обрабатывает извлеченный код и превращает его в операции ввода-вывода (микрооперации), которые затем планируются и выполняются. Процессор имеет кэш этих операций, поэтому он декодирует только те команды, которых еще нет в кэше. Таким образом, развернутый цикл будет заполнять кэш и вызывать столкновение с другим кодом. Меньший код, как правило, лучше.

Что касается массивов, я не уверен, как вы избавитесь от них.

Итак, если у вас было:

struct TextureUnit
{
  // some texture unit data
}

TextureUnit units [number_of_units];

for (int i = 0 ; i < number_of_units ; ++i)
{
  callfunction (units [i].someparams);
}

может быть лучше сделать:

for (TextureUnit *i = unit ; i < &unit [number_of_units] ; ++i)
{
  callfunction (i->someparams);
}

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

Я думаю, что это может быть классифицировано как «микрооптимизация», поэтому я бы не стал беспокоиться об этом, если вы не докажете, что это действительно узкое место. Помните - профилируйте код, не угадывайте.

0 голосов
/ 14 июля 2010

Я не знаю много о компьютерной графике, но этот тривиальный тест показывает, что для TEXTURE_COUNT = 1 и -O1 g ++ не разветвляется. Я подозреваю, что это будет продолжаться даже для многих реальных программ, но почему бы вам не попробовать самим. Используйте -S, чтобы увидеть сгенерированную сборку.

#include <stdio.h>

typedef struct fake_texture
{
    int r, g, b;
} texture;

int main()
{
    texture array[TEXTURE_COUNT] = {};
    for(int i = 0; i < TEXTURE_COUNT; i++)
    {
    array[i].r += 1;
    array[i].g += 2;
    array[i].b += 3;
    }

    for(int i = 0; i < TEXTURE_COUNT; i++)
    {
    printf("%d\n", array[i].r);
    }
}

x86 сборка выдержки:

main:
.LFB31:
        .cfi_startproc
        .cfi_personality 0x0,__gxx_personality_v0
        pushl   %ebp
        .cfi_def_cfa_offset 8
        movl    %esp, %ebp
        .cfi_offset 5, -8
        .cfi_def_cfa_register 5
        andl    $-16, %esp
        subl    $32, %esp
        movl    $1, 20(%esp)
        movl    $2, 24(%esp)
        movl    $3, 28(%esp)
        movl    $1, 8(%esp)
        movl    $.LC0, 4(%esp)
        movl    $1, (%esp)
        call    __printf_chk
        movl    $0, %eax
        leave
        ret
        .cfi_endproc
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...