Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

In every programming language there are sets of opcodes that are recommended over others. I've tried to list them here, in order of speed.

  1. Bitwise
  2. Integer Addition / Subtraction
  3. Integer Multiplication / Division
  4. Comparison
  5. Control flow
  6. Float Addition / Subtraction
  7. Float Multiplication / Division

Where you need high-performance code, C++ can be hand optimized in assembly, to use SIMD instructions or more efficient control flow, data types, etc. So I'm trying to understand if the data type (int32 / float32 / float64) or the operation used (*, +, &) affects performance at the CPU level.

  1. Is a single multiply slower on the CPU than an addition?
  2. In MCU theory you learn that speed of opcodes is determined by the number of CPU cycles it takes to execute. So does it mean that multiply takes 4 cycles and add takes 2?
  3. Exactly what are the speed characteristics of the basic math and control flow opcodes?
  4. If two opcodes take the same number of cycles to execute, then both can be used interchangeably without any performance gain / loss?
  5. Any other technical details you can share regarding x86 CPU performance is appreciated
share|improve this question
12  
This sounds a lot like premature optimization, and remember that the compiler doesn't output what you type in, and you really don't want to write assembly unless you really really have too. –  Roy T. Apr 11 '12 at 10:02
3  
Float multiplication and division are totally different things, you should not put them in the same category. For n-bit numbers, multiplication is a O(n) process, and division is a O(nlogn) process. This makes division about 5 times slower than multiplication on modern CPUs. –  Sam Hocevar Apr 11 '12 at 11:35
    
The only real answer is "profile it". –  Tetrad Apr 11 '12 at 17:00
1  
Expanding on Roy's answer, hand optimizing assembly is almost always going to be a net loss unless you're really really exceptional. Modern CPUs are very complex beasts and good optimizing compilers pull off code transformations that are entirely non-obvious and not trivial to code by hand. Even for SSE/SIMD, always always use intrinsics in C/C++, and let the compiler optimize their usage for you. Using raw assembly disables compiler optimizations and you lose out big. –  Sean Middleditch Apr 11 '12 at 22:19
    
You don't need to hand-optimize to assembly to use SIMD. SIMD is very useful to optimize for depending on the situation, but there is a mostly-standard convention (it works on GCC and MSVC at least) for using SSE2. As far as your list is concerned, on a modern supserscalar multi-pipelined processor, data dependency and register pressure cause more issues than raw integer and sometimes floating point performance; the same is true of data locality. By the way, integer division is the same as multiplication on a modern x86 –  OrgnlDave Apr 12 '12 at 4:19
add comment

2 Answers

up vote 9 down vote accepted

It depends on the CPU in question, but for a modern CPU the list is something like this:

  1. Bitwise, addition, subtraction, comparison, multiplication
  2. Division
  3. Control flow (see answer 3)

Depending on CPU there may be a considerable toll for working with 64 bit data types.

Your questions:

  1. Not at all or not appreciably on a modern CPU. Depend on CPU.
  2. That information is something like 20 to 30 years outdated (School sucks, you have now got proof), modern CPUs handle a variable number of instructions per clock, how many depend on what the scheduler come up with.
  3. Division is a bit slower than the rest, control flow is very fast if the branch prediction is correct, and very slow if it is wrong (something like 20 cycles, depend on CPU). The result is that a lot of code is limited mainly by control flow. Don't do with an if what you can reasonably do with arithmetic.
  4. There is no fixed number for how many cycles any instruction take, but sometimes two different instructions may perform equally, put them in another context and maybe they don't, run them on a different CPU and you are likely to see a 3rd result.
  5. On top of control flow the other big time waster is cache misses, whenever you try to read data that is not in cache the CPU will have to wait for it to be fetched from memory. In general you should try to handle data pieces next to one another simultaneously rather than picking data out from all over the place.

And finally, if you are making a game, don't worry too much about all this, better concentrate on making a good game than chopping CPU cycles.

share|improve this answer
    
I'd also like to point out that the FPU is pretty damn quick: especially on Intel - so fixed-point is only really needed if you want deterministic results. –  Jonathan Dickinson Apr 12 '12 at 11:03
add comment

The intel processor manuals are a free download from their website. They are fairly large but technically can answer your question. The optimization manual in particular is what you are after, but the instruction manual also has the timings and latencies for most of the major CPU lines for simd instructions since they vary from chip to chip.

In general I would consider full branches as well as pointer-chasing (link list traverals, calling virtual functions) the top to perf killers, but the x86/x64 cpus are very good at both, compared to other architectures. If you ever port to another platform you will see how much of a problem they can be, if you are writing high performance code.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.