Используйте эту программу:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#ifdef DIV_BY_DIV
#define DIV(a, b) ((a) / (b))
#else
#define DIV(a, b) (((a) - ((a) % (b))) / (b))
#endif
#ifndef ITERS
#define ITERS 1000
#endif
int main()
{
int i, a, b;
srand(time(NULL));
a = rand();
b = rand();
for (i = 0; i < ITERS; i++)
a = DIV(a, b);
return 0;
}
Вы можете время выполнения
mihai@keldon:/tmp$ gcc -Wall -Wextra -DITERS=1000000 -DDIV_BY_DIV 1.c && time ./a.out
real 0m0.010s
user 0m0.012s
sys 0m0.000s
mihai@keldon:/tmp$ gcc -Wall -Wextra -DITERS=1000000 1.c && time ./a.out
real 0m0.019s
user 0m0.020s
sys 0m0.000s
Или, вы посмотрите на вывод сборки:
mihai@keldon:/tmp$ gcc -Wall -Wextra -DITERS=1000000 -DDIV_BY_DIV 1.c -S; mv 1.s 1_div.s
mihai@keldon:/tmp$ gcc -Wall -Wextra -DITERS=1000000 1.c -S; mv 1.s 1_modulus.s
mihai@keldon:/tmp$ diff 1_div.s 1_modulus.s
24a25,32
> movl %edx, %eax
> movl 24(%esp), %edx
> movl %edx, %ecx
> subl %eax, %ecx
> movl %ecx, %eax
> movl %eax, %edx
> sarl $31, %edx
> idivl 20(%esp)
Как вы видитевыполнение только деления происходит быстрее.
Отредактировано для исправления ошибки в коде, форматирования и неправильного сравнения.
Больше редактирования (объяснение различий в сборке): во втором случае, когда выполняется модульво-первых, сборка показывает, что необходимы две операции idivl
: одна для получения результата %
и одна для фактического деления.Приведенная выше разница показывает вычитание и второе деление, поскольку первое в обоих кодах абсолютно одинаковое.
Редактировать: более актуальная информация о времени:
mihai@keldon:/tmp$ gcc -Wall -Wextra -DITERS=42000000 -DDIV_BY_DIV 1.c && time ./a.out
real 0m0.384s
user 0m0.360s
sys 0m0.004s
mihai@keldon:/tmp$ gcc -Wall -Wextra -DITERS=42000000 1.c && time ./a.out
real 0m0.706s
user 0m0.696s
sys 0m0.004s
Надеюсь, это поможет.
Редактировать: разница между сборками с -O0
и без.
mihai@keldon:/tmp$ gcc -Wall -Wextra -DITERS=1000000 1.c -S -O0; mv 1.s O0.s
mihai@keldon:/tmp$ gcc -Wall -Wextra -DITERS=1000000 1.c -S; mv 1.s noO.s
mihai@keldon:/tmp$ diff noO.s O0.s
Поскольку уровень оптимизации по умолчанию gcc
равен O0
(см. в этой статье, поясняющие уровни оптимизации вgcc
) ожидаемый результат.
Редактировать: если вы скомпилируете с -O3
, как один из комментариев, вы получите ту же сборку, на этом уровне оптимизации, обе альтернативыто же самое.