Improve memory system behavior of core graph execution module.
(1) Precompute some per-node type properties as bits within the NodeItem
data structure, meaning that we can avoid touching the Node* object
for outgoing edges in the critical section.
(2) Change ExecutorState::ActivateNodes to use the NodeItem of the
destination node for each outgoing edge, rather than touching fields
in the *item->node object. Typically this means that we touch 1 or 2
cache lines total for accessing the needed edge data, rather than "~2
+ O(num_outgoing edges)" (and for large graphs with many cores executing
them there is also less TLB pressure).
(3) Added item->is_enter_exit_or_next_iter precomputation and used this
to make the common case first, avoiding three conditional tests and branches
in the common case path in ExecutorState::PropagateOutputs.
Instrumenting the critical section block in
ExecutorState::PropagateOutputs with a CycleTimer and gathering a
histogram of a random sample of the time taken to go through the
critical section shows that this significantly improves the time spent
in the critical section, especially in the tail:
Baseline New
(without this cl) (with this cl)
25%ile 280 ns 250 ns -10.7%
50%ile 510 ns 460 ns -9.8%
90%ile 2170 ns 1740 ns -19.8%
95%ile 4560 ns 2800 ns -38.6%
99%ile 242420 ns 34540 ns -85.8%
Mean 42686 ns 10853 ns -74.6%
A more macro-level benchmark of an image processing input pipeline model
shows ~3.3% performance improvement on my desktop machine.
Change: 146402532
Loading
Please sign in to comment