To elaborate on the justification for the answer: So Intel probably shoved popcnt into the same category to keep the processor design simple In the processor design I work on, we do register dependency checks by partitioning all instructions into a set of "timing classes" and checking the dispatch delay needed between dependent register producers and consumers across all possible timing class pairs. The delays vary d…
Replacing 32-bit loop variable with 64-bit introduces performance deviations
11–20 of 26 posts
Re: Replacing 32-bit loop variable with 64-bit introduces performance deviations
#12Earlier quoted context omitted.
(the uncreatively-named "r8" through "r15".) I'd much rather have numbered registers that can be used for anything than named registers that have usage limitations.
I suspect that aside was written tongue-in-cheek.
Re: Replacing 32-bit loop variable with 64-bit introduces performance deviations
#13I've observed this on both AMD and Intel amd64 CPUs. Not sure how that'd hold up on other CPUs. As always though, profile your code first, and only consider these types of tricks in hot code areas.
Re: Replacing 32-bit loop variable with 64-bit introduces performance deviations
#14To elaborate on the justification for the answer: So Intel probably shoved popcnt into the same category to keep the processor design simple In the processor design I work on, we do register dependency checks by partitioning all instructions into a set of "timing classes" and checking the dispatch delay needed between dependent register producers and consumers across all possible timing class pairs. The delays vary d…
Re: Replacing 32-bit loop variable with 64-bit introduces performance deviations
#15Re: Replacing 32-bit loop variable with 64-bit introduces performance deviations
#16To elaborate on the justification for the answer: So Intel probably shoved popcnt into the same category to keep the processor design simple In the processor design I work on, we do register dependency checks by partitioning all instructions into a set of "timing classes" and checking the dispatch delay needed between dependent register producers and consumers across all possible timing class pairs. The delays vary d…
I wouldn't classify it as intentional nor a "bug"; probably it's more of an oversight, as it's mentioned in the article that AMD's CPUs don't have this issue. Intel should definitely be made aware of this. We can only speculate, but it's likely that Intel has the same handling for a lot two-operand instructions. Common instructions like add, sub take two operands both of which are inputs. So Intel probably shoved pop…
It would be interesting to see if the Intel C Compiler knows about this false dependency.
Re: Replacing 32-bit loop variable with 64-bit introduces performance deviations
#17To elaborate on the justification for the answer: So Intel probably shoved popcnt into the same category to keep the processor design simple In the processor design I work on, we do register dependency checks by partitioning all instructions into a set of "timing classes" and checking the dispatch delay needed between dependent register producers and consumers across all possible timing class pairs. The delays vary d…
Re: Replacing 32-bit loop variable with 64-bit introduces performance deviations
#18It should be noted that using 64-bit operands, even in 64-bit mode, incurs an extra penalty of 1 byte per instruction, for the REX prefix. The same applies to using the extended registers (the uncreatively-named "r8" through "r15".) This is very much not noticeable for microbenchmarks, where all the code of a loop fits in the cache, but for bigger ones, the effects of icache misses can become quite significant. A sma…
Any hope to see a Thumb mode for x86-64?
Re: Replacing 32-bit loop variable with 64-bit introduces performance deviations
#19Earlier quoted context omitted.
I wouldn't classify it as intentional nor a "bug"; probably it's more of an oversight, as it's mentioned in the article that AMD's CPUs don't have this issue. Intel should definitely be made aware of this. We can only speculate, but it's likely that Intel has the same handling for a lot two-operand instructions. Common instructions like add, sub take two operands both of which are inputs. So Intel probably shoved pop…
Reg-Reg MOV doesn't use an ALU, though. It would be interesting to see if the Intel C Compiler knows about this false dependency.
Here's icpc 14.0.3 vs g++ 4.8.1 on a Sandy Bridge E5-1620 @ 3.60GHz and a Haswell i7-4770 CPU @ 3.40GHz.
nate@sandybridge:~/tmp$ g++ -O3 -march=native -std=c++11 popcnt-dependency.cpp -o popcnt-dependency
nate@sandybridge:~/tmp$ popcnt-dependency 1
unsigned 41959360000 0.608615 sec 17.2289 GB/s
uint64_t 41959360000 0.82312 sec 12.739 GB/s
nate@sandybridge:~/tmp$ icpc -O3 -march=native -std=c++11 popcnt-dependency.cpp -o popcnt-dependency
nate@sandybridge:~/tmp$ popcnt-dependency 1
unsigned 41959360000 0.182781 sec 57.3679 GB/s
uint64_t 41959360000 0.182638 sec 57.4128 GB/s
nate@haswell:~/tmp$ g++ -O3 -march=native -std=c++11 popcnt-dependency.cpp -o popcnt-dependency
nate@haswell:~/tmp$ popcnt-dependency 1
unsigned 41959360000 0.401225 sec 26.1343 GB/s
uint64_t 41959360000 0.75841 sec 13.826 GB/s
nate@haswell:~/tmp$ icpc -O3 -march=native -std=c++11 popcnt-dependency.cpp -o popcnt-dependency
nate@haswell:~/tmp$ popcnt-dependency 1
unsigned 41959360000 0.0843861 sec 124.259 GB/s
uint64_t 41959360000 0.0842836 sec 124.41 GB/s
That would be incredible if true! But I think it's a bug, since the inner loop looks far too short and doesn't seem to be repeating the popcnt's. I'm not sure yet if it's a problem with the compiler or if the test case is abusing something undefined.Re: Replacing 32-bit loop variable with 64-bit introduces performance deviations
#20Earlier quoted context omitted.
Reg-Reg MOV doesn't use an ALU, though. It would be interesting to see if the Intel C Compiler knows about this false dependency.
'icpc' (the Intel C++ compiler) has equal performance for both of the test cases, and it did choose to use different registers for each call. But it's not clear if that's by design or by chance. In some ways, that's the boring part. The interesting part (to me) is that both tests are much faster than either version with g++. Here's icpc 14.0.3 vs g++ 4.8.1 on a Sandy Bridge E5-1620 @ 3.60GHz and a Haswell i7-4770 CPU…
nate@sandybridge:~/tmp$ popcnt-dependency 1
unsigned 41959360000 0.517827 sec 20.2495 GB/s
uint64_t 41959360000 0.518041 sec 20.2412 GB/s
nate@haswell:~/tmp$ popcnt-dependency 1
unsigned 41959360000 0.351273 sec 29.8507 GB/s
uint64_t 41959360000 0.352914 sec 29.712 GB/s
The other test I did was checking what Intel's IACA (a wonderful optimization tool that you really should be using if you are not already) thought about the g++ loop. It did _not_ notice the false dependency, and said the loops should take the same amount of time. Do this suggest that the Intel compiler is just getting lucky, or that Intel doesn't have great internal communication between teams?