4 ms·
Doesn't the optimizing compiler of C just replace the entire loop with a single assignment or even a no-op? Not sure if benchmarking was done properly here.
by nlitened 5y ago
Doesn't the optimizing compiler of C just replace the entire loop with a single assignment or even a no-op? Not sure if benchmarking was done properly here.
- qiqitori 5y agoYes, it does. -O0 executes the loop as coded. (0.6s on my machine) -O1 executes the loop faster. (0.152s on my machine) -O2 and beyond just figure out the result and are equivalent to one strtol + printf. So what's different between -O0 and -O1? $ cc -O0 -g -o c_loop c_loop.c $ objdump -M intel-mnemonic -S c_loop 0000000000001145 <main>: ... for (s = i = 0; i < NUMBER; ++i) { 116a: c7 45 fc 00 00 00 00 mov DWORD PTR [rbp-0x4],0x0 1171: 8b 45 fc mov eax,DWORD PTR [rbp-0x4] 1174: 89 45 f8 mov DWORD PTR [rbp-0x8],eax 1177: eb 08 jmp 1181 <main+0x3c> s += 1; 1179: 83 45 f8 01 add DWORD PTR [rbp-0x8],0x1 for (s = i = 0; i < NUMBER; ++i) { 117d: 83 45 fc 01 add DWORD PTR [rbp-0x4],0x1 1181: 8b 45 fc mov eax,DWORD PTR [rbp-0x4] 1184: 3b 45 f4 cmp eax,DWORD PTR [rbp-0xc] 1187: 7c f0 jl 1179 <main+0x34> } printf("s: %d",s); 1189: 8b 45 f8 mov eax,DWORD PTR [rbp-0x8] 118c: 89 c6 mov esi,eax 118e: 48 8d 3d 6f 0e 00 00 lea rdi,[rip+0xe6f] # 2004 <_IO_stdin_used+0x4> 1195: b8 00 00 00 00 mov eax,0x0 119a: e8 91 fe ff ff call 1030 <printf@plt> return 0; 119f: b8 00 00 00 00 mov eax,0x0 } The take-home here is that it uses the stack (DWORD PTR ...) for almost everything. Just the eax, rdi, esi registers are used. The core loop is four instructions, add, mov, cmp, jl. Caches still make this relatively fast. $ cc -O1 -g -o c_loop c_loop.c $ objdump -M intel-mnemonic -S c_loop 0000000000001145 <main>: ... // NOTE: NUMBER is in eax at this point for (s = i = 0; i < NUMBER; ++i) { 115c: 85 c0 test eax,eax 115e: 7e 29 jle 1189 <main+0x44> 1160: 89 c6 mov esi,eax 1162: b8 00 00 00 00 mov eax,0x0 s += 1; 1167: 83 c0 01 add eax,0x1 for (s = i = 0; i < NUMBER; ++i) { 116a: 39 f0 cmp eax,esi 116c: 75 f9 jne 1167 <main+0x22> } printf("s: %d",s); 116e: 48 8d 3d 8f 0e 00 00 lea rdi,[rip+0xe8f] # 2004 <_IO_stdin_used+0x4> 1175: b8 00 00 00 00 mov eax,0x0 117a: e8 b1 fe ff ff call 1030 <printf@plt> The take-home here is that registers are being used. The core loop is three instructions now (add, cmp, jne), we don't need the MOV anymore.
- IshKebab 5y agoYeah not only do they screw up the benchmarking, but they somehow conclude that you shouldn't give up on Python even though it is 45000 times slower than C! > Should I give up Python then? No. Madness. In my experience Python is on the order of 100 times slower than "fast" languages like C, C++, Go, Rust, Zig, Java, etc.