Eric Dumazet a écrit : > On Tuesday 06 March 2007 18:28, Eric Dumazet wrote: >> On Tuesday 06 March 2007 18:19, Linus Torvalds wrote: >> >>>> Using reciprocal divides permits to change each divide by two >>>> multiplies, less expensive on current CPUS. >>> Are you sure? >> I am going to test this, but at least on Opterons, the reciprocal divide I >> added into mm/slab.c gave me a nice speedup. >> > Linus, I did a user space program, attached to this mail. I rewrote the reciprocal_div() for i386 so that one multiply is used. static inline u32 reciprocal_divide(u32 A, u32 R) { #if __i386 unsigned int edx, eax; asm("mul %2":"=a" (eax), "=d" (edx):"rm" (R), "0" (A)); return edx; #else return (u32)(((u64)A * R) >> 32); #endif } Results are really good on 32bit. On 64bit/Opteron they are impressive. $ gcc -O2 -o divide_bench divide_bench.c First result gives the number of cycles to perform old number() routine using plain do_div() Second result gives the number of cycles using reciprocal_div trick results on a Intel Pentium III 866 MHz $ ./divide_bench 413.453 cycles per call, last res=99999901 132.746 cycles per call, last res=99999901 $ ./divide_bench 411.833 cycles per call, last res=99999901 129.652 cycles per call, last res=99999901 $ ./divide_bench 480.645 cycles per call, last res=99999901 158.642 cycles per call, last res=99999901 $ ./divide_bench 412.769 cycles per call, last res=99999901 129.643 cycles per call, last res=99999901 $ ./divide_bench 410.809 cycles per call, last res=99999901 129.609 cycles per call, last res=99999901 results on AMD 246 (2GHz) Sorry this machine is quite loaded... I dont have a dev x86_64 machine. $ gcc -O2 -m32 -o divide_bench32 divide_bench.c $ ./divide_bench32 412.181 cycles per call, last res=99999901 112.314 cycles per call, last res=99999901 $ ./divide_bench32 444.008 cycles per call, last res=99999901 114.314 cycles per call, last res=99999901 $ ./divide_bench32 423.168 cycles per call, last res=99999901 112.318 cycles per call, last res=99999901 $ ./divide_bench32 427.73 cycles per call, last res=99999901 110.712 cycles per call, last res=99999901 $ ./divide_bench32 410.529 cycles per call, last res=99999901 114.068 cycles per call, last res=99999901 $ ./divide_bench32 489.856 cycles per call, last res=99999901 124.889 cycles per call, last res=99999901 $ ./divide_bench32 389.278 cycles per call, last res=99999901 104.697 cycles per call, last res=99999901 With a 64bit prog : $ gcc -O2 -m64 -o divide_bench64 divide_bench.c $ ./divide_bench64 826.136 cycles per call, last res=99999901 105.912 cycles per call, last res=99999901 $ ./divide_bench64 627.096 cycles per call, last res=99999901 76.2473 cycles per call, last res=99999901 $ ./divide_bench64 604.524 cycles per call, last res=99999901 76.1405 cycles per call, last res=99999901 $ ./divide_bench64 621.013 cycles per call, last res=99999901 76.0963 cycles per call, last res=99999901 $ ./divide_bench64 836.799 cycles per call, last res=99999901 103.967 cycles per call, last res=99999901 $ ./divide_bench64 982.718 cycles per call, last res=99999901 127.945 cycles per call, last res=99999901 $ ./divide_bench64 609.346 cycles per call, last res=99999901 76.0768 cycles per call, last res=99999901