Live data from Hacker News

Operation Costs in CPU Clock Cycles

ithare.com

11–20 of 69 posts

Re: Operation Costs in CPU Clock Cycles

#11
post #6
post #4

Earlier quoted context omitted.

A virtual call in C++ is just a vtable lookup then a direct C call. Literally one pointer away. (or perhaps one pointer then one integer addition away? For the offset)

one pointer can be as slow as a sqrt if it isn't in cache.

The cost of virtual calls (and calls in general) in the article is greatly exaggerated. Jumps, calls and indirect calls have an effective latency of zero as they are resolved in the fetch stage (and speculated if the target is not known) and a troughput of one taken jump every one or two cycles.

In a virtual call, the offset computation and load is only used to compute the jump target (which is only used later on commit), which means that is not on the critical path [1].

They consume execution and load bandwith, but that's not normally the bottleneck. The cost of virtual cals is usually due to missed optimizations and the possibility of misprediction.

[1] technically if the load is delayed long enough, the CPU might be prevented from committing the speculated instructions and eventually exhaust its reoerder buffer and stall.

Re: Operation Costs in CPU Clock Cycles

#13
While this is a pretty decent overview, it is not very precise, and even a bit misleading in certain cases. Depending on where certain instructions are in the execution pipeline, you can. R limited in what can be issued and executed, and the latencies are not deterministic. This is one of the biggest difficulties in optimizing scheduling in a complex architecture such as x86, and gets even worse (determinism wise) when you throw in cache misses and branch prediction.

For a more exhaustive instruction latency listing over a variety of micro architectures, check out [0]. [1] is also a great resource for memory latencies for a variety of processors.

[0]: http://www.agner.org/optimize/instruction_tables.pdf

[1]: http://www.7-cpu.com

Re: Operation Costs in CPU Clock Cycles

#14
post #4
post #3

The small difference between direct C calls and virtual C++ calls surprised me, actually. I thought it would be much bigger.

A virtual call in C++ is just a vtable lookup then a direct C call. Literally one pointer away. (or perhaps one pointer then one integer addition away? For the offset)

Is it that simple for virtual methods in complex class hierarchies? If the class hierarchy isn't linear, how can you assign simple absolute vtable indices for methods?

Re: Operation Costs in CPU Clock Cycles

#15

Anyone have the presentation from a Intel guy on how the CPU design focus has moved from cycles to cache misses handy? Edit: never mind, it was not a Intel guy. And i actually had the thing bookmarked (and it still worked). https://www.infoq.com/presentations/click-crash-course-moder...

There's a fantastic, massively upvoted StackOverflow post that can also provide some insight here. This may be a little more accessible, since it's such a significant runtime difference with very simple source code.

http://stackoverflow.com/questions/11227809/why-is-it-faster...

Re: Operation Costs in CPU Clock Cycles

#16
post #3

The small difference between direct C calls and virtual C++ calls surprised me, actually. I thought it would be much bigger.

An important factor is whether it can be branch predicted. If the virtual call nearly always goes to the same method implementation (e.g., always an OpenGL renderer or always a DirectX renderer), it can actually be pretty cheap. They get expensive mainly when the call is constantly jumping to implementations for different object types.

Re: Operation Costs in CPU Clock Cycles

#17
post #3

The small difference between direct C calls and virtual C++ calls surprised me, actually. I thought it would be much bigger.

Even then, the article and co-commentators exaggerate the cost and factors you should worry about for virtual calls. Unless you're optimizing specifically for an in-order CPU, the only cost of virtual functions that really matters in the general/high level case is not being able to inline them.

Re: Operation Costs in CPU Clock Cycles

#18
post #15

Anyone have the presentation from a Intel guy on how the CPU design focus has moved from cycles to cache misses handy? Edit: never mind, it was not a Intel guy. And i actually had the thing bookmarked (and it still worked). https://www.infoq.com/presentations/click-crash-course-moder...

There's a fantastic, massively upvoted StackOverflow post that can also provide some insight here. This may be a little more accessible, since it's such a significant runtime difference with very simple source code. http://stackoverflow.com/questions/11227809/why-is-it-faster...

The question is very interesting and good phrased, and the answer is better than many classes that many students had about processors and so on.

Re: Operation Costs in CPU Clock Cycles

#19
post #12

I'm surprised how fast a C function call is. I would have thought that creating a stack frame would be slower than that, (and significantly slower than a floating point division), but I guess not.

That's because nothing is created. A function call is just putting some registers on the stack and jumping somewhere else. Stack growth etc. is typically handled implicitly by the OS (if a write on the stack pagefaults more stack memory is allocated).

Contrary to eg. an interpreter where a stack frame would usually be a real, dedicated object that is allocated when a frame is needed.

Re: Operation Costs in CPU Clock Cycles

#20
post #4

Earlier quoted context omitted.

A virtual call in C++ is just a vtable lookup then a direct C call. Literally one pointer away. (or perhaps one pointer then one integer addition away? For the offset)

Is it that simple for virtual methods in complex class hierarchies? If the class hierarchy isn't linear, how can you assign simple absolute vtable indices for methods?

Yes it is. The C++ ABI defines how any permitted inheritance hierarchy is mapped into a surjective, ordered set of vtables. Also, calls into methods of other classes in the hierarchy offset the this pointer accordingly.

It feels counterintuitive that these two mechanisms are sufficient; but they are.

Post reply on HN