Модуль против оператора if в цикле

0

У меня такой цикл:

for(i = 0; i < arrayLength; i++)
{
    result[i / 8] = SETBIT(result[i / 8], ++(*bitIndex), array[i]);
    *bitIndex %= 8;
}

Интересно, что лучше, с точки зрения производительности, если я использую вышеупомянутый стиль или этот стиль:

for(i = 0; i < arrayLength; i++)
{
    result[i / 8] = SETBIT(result[i / 8], ++(*bitIndex), array[i]);
    if(*bitIndex == 8) *bitIndex = 0;
}

Это в C, составленном с помощью GCC, объяснение также будет оценено.

благодаря

  • 5
    Измерить. Оптимизация. Измерить. Любой ответ на этот вопрос будет зависеть от версии компилятора и его настроек оптимизации. И следующий выпуск может сделать ответ недействительным.
  • 0
    и вместо деления на 8 вы можете использовать: i >> 3; он не медленнее, чем i / 8, но может быть быстрее в зависимости от параметров компилятора и т. д.
Показать ещё 6 комментариев
Теги:

3 ответа

0
Лучший ответ

Честно говоря, между ними будет только часть второй разницы. Но я считаю, что первая была бы ТАКЖЕ лучше для простого стиля READING. Тем не менее, этот вопрос ссылается на производительность, в которой я все еще думаю, что у первого будет край EVER SO SLIGHT для того, что компилятор читает/вычисляет меньше информации.

5

Нет смысла говорить об оптимизации...

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

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

for(i = 0; i < arrayLength; i++)
{
    (*bitIndex)++;
    SETBIT(&result[i / 8], *bitIndex, array[i]);
    *bitIndex %= 8;
}

Вероятно, это даст тот же бинарный исполняемый файл, что и у вас, + - несколько тиков процессора.

0

Вы не говорите, почему bitIndex - это указатель. Но, предполагая, что bitIndex является параметром функции, содержащей данный цикл, я бы вытащил *bitIndex материал из цикла, так что:

  unsigned bi = *bitIndex ;

  for(i = 0 ; i < arrayLength ; i++)
    {
      result[i / 8] = SETBIT(&result[i / 8], ++bi, array[i]) ;
      bi %= 8 ;
    } ;

   *bitIndex = bi ;

[Я предполагаю, что ++bi правильный, и что SETBIT() требует 1..8, где bi равно 0..7.]

Как отмечалось в других местах, компилятор имеет % 8 на завтрак и заменяет его на & 0x7 (для неподписанных, но не для подписанных). С помощью gcc -O2 выше выведен цикл из 48 байтов кода (15 команд). Скрипт с *bitIndex в цикле составлял 50 байтов кода (16 команд), включая чтение и две записи *bitIndex.

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

Если bitIndex является указателем на локальную переменную, тогда компилятор будет вытаскивать значение в регистр на протяжении всего цикла, поэтому он считает, что это стоит того!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню