Для назначения курса под названием High Performance Computing мне необходимо оптимизировать следующий фрагмент кода:
int foobar(int a, int b, int N)
{
int i, j, k, x, y;
x = 0;
y = 0;
k = 256;
for (i = 0; i <= N; i++) {
for (j = i + 1; j <= N; j++) {
x = x + 4*(2*i+j)*(i+2*k);
if (i > j){
y = y + 8*(i-j);
}else{
y = y + 8*(j-i);
}
}
}
return x;
}
Используя некоторые рекомендации, мне удалось оптимизировать код (или, по крайней мере, я так думаю), например:
- Постоянное распространение
- Алгебраическое упрощение
- Копирование распространения
- Устранение общих подвыражений
- Устранение мертвого кода
- Инвариантное удаление цикла
- побитовые сдвиги вместо умножения, поскольку они менее дороги.
Здесь мой код:
int foobar(int a, int b, int N) {
int i, j, x, y, t;
x = 0;
y = 0;
for (i = 0; i <= N; i++) {
t = i + 512;
for (j = i + 1; j <= N; j++) {
x = x + ((i<<3) + (j<<2))*t;
}
}
return x;
}
Согласно моему инструктору, хорошо оптимизированные инструкции кода должны иметь меньше или менее дорогостоящих инструкций на уровне языка ассемблера. И поэтому должны выполняться инструкции за меньшее время, чем исходный код, то есть расчеты выполняются с::
время выполнения = количество команд * циклов на команду
Когда я генерирую код сборки с помощью команды: gcc -o code_opt.s -S foobar.c
,
сгенерированный код имеет гораздо больше строк, чем оригинал, несмотря на то, что он сделал некоторые оптимизации, а время выполнения меньше, но не так сильно, как в исходном коде. Что я делаю неправильно?
Не вставляйте код сборки, поскольку они очень обширны. Поэтому я вызываю функцию "foobar" в основном, и я измеряю время выполнения, используя команду time в linux
int main () {
int a,b,N;
scanf ("%d %d %d",&a,&b,&N);
printf ("%d\n",foobar (a,b,N));
return 0;
}