Live data from Hacker News

Performance Hints

abseil.io

21–30 of 46 posts

Re: Performance Hints

#21
post #2

This formatting is more intuitive to me. L1 cache reference 2,000,000,000 ops/sec L2 cache reference 333,333,333 ops/sec Branch mispredict 200,000,000 ops/sec Mutex lock/unlock (uncontended) 66,666,667 ops/sec Main memory reference 20,000,000 ops/sec Compress 1K bytes with Snappy 1,000,000 ops/sec Read 4KB from SSD 50,000 ops/sec Round trip within same datacenter 20,000 ops/sec Read 1MB sequentially from memory 15,62…

I’ve seen this list many many times and I’m always surprised it doesn’t include registers.

Register moves do not really play a factor in performance, unless its to move to/from vector registers.

Re: Performance Hints

#22
post #10

Earlier quoted context omitted.

I prefer a different encoding: cycles/op Both ops/sec and sec/op vary on clock rate, and clock rate varies across machines, and along the execution time of your program. AFAIK, Cycles (a la _rdtsc) is as close as you can get to a stable performance measurement for an operation. You can compare it on chips with different clock rates and architectures, and derive meaningful insight. The same cannot be said for op/sec o…

Unfortunately, what you'll find if you dig into this is that cycles/op isn't as meaningful as you might imagine. Most modern CPUs are out of order executors. That means that while a floating point operation might take 4 cycles to complete, if you put a bunch of other instructions around it like adds, divides, and multiplies, those will all finish at roughly the same time. That makes it somewhat hard to reason about e…

Your critique applies to measuring one or a handful of instructions. In practice you count the number of cycles over million or billion instructions. CPI is very meaningful and it is the main throughput performance metric for CPU core architects.

Re: Performance Hints

#23
post #10

Earlier quoted context omitted.

I prefer a different encoding: cycles/op Both ops/sec and sec/op vary on clock rate, and clock rate varies across machines, and along the execution time of your program. AFAIK, Cycles (a la _rdtsc) is as close as you can get to a stable performance measurement for an operation. You can compare it on chips with different clock rates and architectures, and derive meaningful insight. The same cannot be said for op/sec o…

Unfortunately, what you'll find if you dig into this is that cycles/op isn't as meaningful as you might imagine. Most modern CPUs are out of order executors. That means that while a floating point operation might take 4 cycles to complete, if you put a bunch of other instructions around it like adds, divides, and multiplies, those will all finish at roughly the same time. That makes it somewhat hard to reason about e…

I agree that what you're saying is true, but in the context of my comment, I stand by the statement that cycles/op is still a more meaningful measurement of performance than seconds.

---

Counter-nitpick .. your statement of "if you put a bunch of other instructions around it" assumes there are no data dependencies between instructions.

In the example you gave:

    FloatMul
    ADD
    MUL
    DIV
Sure .. if all of those are operating on independent data sources, they could conceivably retire on the same cycle, but in the context of the article (approximating the performance profile of a series of operations) we're assuming they have data dependencies on one another, and are going to be executed serially.

Re: Performance Hints

#24
post #4

Earlier quoted context omitted.

Just be careful not to blindly apply the same techniques to a mobile or desktop class CPU or above. A lot of code can be pessimized by golfing instruction counts, hurting instruction-level parallelism and microcode optimizations by introducing false data dependencies. Compilers outperform humans here almost all the time.

Compilers massively outperform humans if the human has to write the entire program in assembly. Even if a human could write a sizable program in assembly, it would be subpar compared to what a compiler would write. This is true. However, that doesn't mean that looking at the generated asm / even writing some is useless! Just because you can't globally outperform the compiler, doesn't mean you can't do it locally ! If…

yo, completely off topic, but do you work on a voxel game/engine?

Re: Performance Hints

#25
post #2

This formatting is more intuitive to me. L1 cache reference 2,000,000,000 ops/sec L2 cache reference 333,333,333 ops/sec Branch mispredict 200,000,000 ops/sec Mutex lock/unlock (uncontended) 66,666,667 ops/sec Main memory reference 20,000,000 ops/sec Compress 1K bytes with Snappy 1,000,000 ops/sec Read 4KB from SSD 50,000 ops/sec Round trip within same datacenter 20,000 ops/sec Read 1MB sequentially from memory 15,62…

Your suggestion confuses latency and throughput. So it isn't correct. For example, a modern CPU will be able to execute other instructions while waiting for a cache miss, and will also be able to have multiple cache loads in flight at once (especially for caches shared between cores). Main memory is asynchronous too, so multiple loads might be in flight, per memory channel. Same goes for all the other layers here (mu…

I'm aware of this to an extent. Do you know of any list of what degree of parallelization to expect out of various components? I know this whole napkin-math thing is mostly futile and the answer should mostly be "go test it", but just curious.

I was interviewing recently and was asked about implementing a web crawler and then were discussing bottlenecks (network fetching the pages, writing the content to disk, CPU usage for stuff like parsing the responses) and parallelism, and I wanted to just say "well, i'd test it to figure out what I was bottlenecked on and then iterate on my solution".

Re: Performance Hints

#26

Earlier quoted context omitted.

I’ve seen this list many many times and I’m always surprised it doesn’t include registers.

Register moves do not really play a factor in performance, unless its to move to/from vector registers.

H+P says register allocation is one of the most important—if not the most important—optimizations.

Re: Performance Hints

#27

Earlier quoted context omitted.

Register moves do not really play a factor in performance, unless its to move to/from vector registers.

H+P says register allocation is one of the most important—if not the most important—optimizations.

In cpu uarch design, sure, but that's outside the context of the discussion. There's nothing you can do to that C++ library you are optimizing that will impact performance due to register allocation/renaming.

Re: Performance Hints

#28

Earlier quoted context omitted.

Your suggestion confuses latency and throughput. So it isn't correct. For example, a modern CPU will be able to execute other instructions while waiting for a cache miss, and will also be able to have multiple cache loads in flight at once (especially for caches shared between cores). Main memory is asynchronous too, so multiple loads might be in flight, per memory channel. Same goes for all the other layers here (mu…

I'm aware of this to an extent. Do you know of any list of what degree of parallelization to expect out of various components? I know this whole napkin-math thing is mostly futile and the answer should mostly be "go test it", but just curious. I was interviewing recently and was asked about implementing a web crawler and then were discussing bottlenecks (network fetching the pages, writing the content to disk, CPU us…

Napkin math is how you avoid spending several weeks of your life going down ultimately futile rabbit holes. Yes, it's approximations, often very coarse ones, but done right they do work.

Your question about what degree of parallelization is unfortunately too vague to really answer. SSDs offer some internal parallelism. Need more parallelism / IOPS? You can stick a lot more SSDs on your machine. Need many machines worth of SSDs? Disaggregate them, but now you need to think about your network bandwidth, NICs, cross-machine latency, and fault-tolerance.

The best engineers I've seen are usually excellent at napkin math.

Re: Performance Hints

#29
I wish Google would open source their gtl library. Similar utilities exist elsewhere but not in the same consistent quality and well-integrated package.

I particularly like the “what to do for flat profiles” ad “protobuf tips” sections. Similar advice distilled to this level is difficult to find elsewhere.

Re: Performance Hints

#30

Earlier quoted context omitted.

H+P says register allocation is one of the most important—if not the most important—optimizations.

In cpu uarch design, sure, but that's outside the context of the discussion. There's nothing you can do to that C++ library you are optimizing that will impact performance due to register allocation/renaming.

This is not always true. Compilers are quite good at register allocation but sometimes they get it wrong and sometimes you can make small changes to code that improve register allocation and thus performance.

Usually the problem is an unfortunately placed spill, so the operation is actually l1d$ traffic, but still.

Post reply on HN