(cpu_atom "<not counted>" lines omitted below; see lab 01 for why they exist)
$ ../tools/pin.sh -q perf stat -e cycles:u,instructions:u,branches:u,branch-misses:u ./bin/02_counters branch-sorted
what it printed on the machine that wrote this lab
301,619,631 cpu_core/cycles/u
1,455,602,504 cpu_core/instructions/u # 4.83 insn per cycle
432,062,143 cpu_core/branches/u
2,773 cpu_core/branch-misses/u # 0.00% of all branches
$ ../tools/pin.sh -q perf stat -e cycles:u,instructions:u,branches:u,branch-misses:u ./bin/02_counters branch-random
what it printed on the machine that wrote this lab
2,334,724,280 cpu_core/cycles/u
1,409,457,710 cpu_core/instructions/u # 0.60 insn per cycle
427,866,447 cpu_core/branches/u
83,885,665 cpu_core/branch-misses/u # 19.61% of all branches
Read it:
- `instructions` and `branches` agree to within 3%: the two runs execute
the SAME program on the same amount of data. Time differs 7.7x in cycles.
- The only counter that moved is branch-misses: 2.8 thousand vs 83.9
MILLION. The loop runs 160M iterations (10 passes x 16M bytes) and the
`>= 128` test is a coin flip on random data, so the predictor is wrong
~80M times = half the time. "19.61% of all branches" is lower than 50%
only because the loop back-edge and the other ~2 branches per iteration
are predicted perfectly.
- Cost per mispredict: (2334.7M - 301.6M cycles) / 83.9M = ~24 cycles.
That is the pipeline flush + refill on this core. IPC collapses from
4.83 to 0.60 because after every flush the core starts over.
This is the classic "why is processing a sorted array faster" question,
and the counter IS the answer. The `:u` suffix = user-space only, which is
what unprivileged perf may count (perf_event_paranoid=2 on this box).