Управление оптимизацией GCC - PullRequest
1 голос
/ 17 марта 2011

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

Код выглядит так:

clock1 = get_ticks()
for (i = 0; i < 1000000; i++) {
  for (j = 0; j < (workingset * stride / sizeof(data_t)); j += stride) {
    *array[j];
  }
}
clock2 = get_ticks()

Теперь проблема в том, что при разумном уровне оптимизации gcc будетоптимизировать чтение, потому что оно не имеет побочных эффектов.У меня не может быть никакого уровня оптимизации, иначе все переменные цикла вызовут чтение в память.Я пробовал несколько разных вещей, таких как создание массива volatile и использование встроенных функций, которые приводят к volatile, но обработка изменяемых переменных в gcc предсказать очень сложно.Как правильно это сделать?

Ответы [ 4 ]

2 голосов
/ 17 марта 2011

Одной из возможностей является использование данных массива способом, который невозможно легко оптимизировать, например,

clock1 = get_ticks();
sum = 0;
for (i = 0; i < 1000000; i++) {
  for (j = 0; j < (workingset * stride / sizeof(data_t)); j += stride) {
    sum += array[j];
  }
}
clock2 = get_ticks();
return sum;

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

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

1 голос
/ 17 марта 2011

Для GCC попробуйте указать used атрибут для всех индексных переменных (i, j), чтобы избежать оптимизации компилятором для них (даже с включенной опцией глобальной оптимизации):

int i __attribute__((used));
int j __attribute__((used));

clock1 = get_ticks()
for (i = 0; i < 1000000; i++) {
  for (j = 0; j < (workingset * stride / sizeof(data_t)); j += stride) {
    *array[j];
    asm (""); // help to avoid cycle's body elimination
  }
}
clock2 = get_ticks();

Также полезно знать, что выражения asm(...) никогда не оптимизируются.Вы даже можете использовать его без какого-либо выражения ассемблера, например: asm("");.

0 голосов
/ 17 марта 2011

Сохранять значение в глобальной переменной volatile на каждой итерации.Это обеспечит фактическую запись (что необходимо для гарантии того, что в обработчике сигнала будет видно правильное значение).

В качестве альтернативы используйте что-то вроде

sum += *array[j]^i;

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

0 голосов
/ 17 марта 2011

Я думаю, что вы действительно должны попытаться написать это на ассемблере, если вы не хотите, чтобы компилятор с этим справлялся. Вы просто не можете гарантировать, что какие-то "уловки" будут работать вечно. То, что работает сейчас, может быть оптимизировано в будущей версии компилятора. Также, вероятно, трудно предсказать, сработало ли это. Если вы можете проверить ассемблерный код, чтобы убедиться, что он работает (т.е. не оптимизировал его), вы также сможете написать его с нуля?

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