Ручное разматывание циклов может быть неэффективным на более новых процессорах, но они все еще могут быть полезны на графических процессорах и легких архитектурах, таких как ARM, поскольку они не так хороши, как процессоры процессоров текущего поколения при прогнозировании, а также потому, что тесты и переходы фактически тратят циклы на этих процессорах .
Тем не менее, это должно быть сделано только на очень узких циклах и в блоках, потому что при развертывании вы значительно увеличиваете размер кода, и это приведет к увеличению объема кеша на небольших устройствах, и вы получите гораздо худшую проблему на руке .
Однако, предупреждение о том, что развертывание цикла должно быть самым последним средством при оптимизации. Он извращает ваш код на том уровне, который делает его неприемлемым, и кто-то, читающий его, может в дальнейшем осквернить вас и вашу семью. Зная это, сделай это того:)
Использование макросов может значительно помочь сделать код более читабельным, а развертывание - преднамеренным.
Пример:
for(int i=0; i<256; i++)
{
a+=(ptr + i) << 8;
a-=(ptr + i - k) << 8;
// And possibly some more
}
Можно развернуть до:
#define UNROLL (i) \
a+=(ptr[i]) << 8; \
a-=(ptr[i-k]) << 8;
for(int i=0; i<32; i++)
{
UNROLL(i);
UNROLL(i+1);
UNROLL(i+2);
UNROLL(i+3);
UNROLL(i+4);
UNROLL(i+5);
UNROLL(i+6);
UNROLL(i+7);
}
На несвязанной ноте, но все еще в некоторой степени связанной, если вы действительно хотите выиграть на стороне подсчета команд, убедитесь, что все константы объединены в как можно меньшее количество непосредственных элементов в вашем коде, чтобы вы не получили следующее монтаж:
// Bad
MOV r1, 4
// ...
ADD r2, r2, 1
// ...
ADD r2, r2, 4
Вместо:
// Better
ADD r2, r2, 8
Обычно серьезные компиляторы защищают вас от подобных вещей, но не все будут. Держите эти «#define», «enum» и «static const» под рукой, не все компиляторы будут оптимизировать локальные переменные «const».