Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Fix 1:
scx_rusty: make per-task loads sensitive to lb_apply_weight
Rusty's load balancer calculates load differently based on average system CPU utilization in create_domain_hierarchy(). At >= 99.999% utilization, load is the product of a task's weight and duty cycle; below that, load is the same as the task's duty cycle.
populate_tasks_by_load(), however, always uses the product when calculating per-task load so that in the sub-99.999% util case, load is inflated, typically by a factor of 100 with a normal priority task. Tasks look too heavy to migrate as a result because a single task would transfer more load than the domain imbalance allows, leading to significant imbalance in some cases.
Make populate_tasks_by_load() calculate task load the same way as domain load, checking lb_apply_weight.
Here's a CPU utilization heatmap from an EPYC server before the fix. Each pair of CPU rows are SMT siblings, every 16 CPUs are an LLC, and the top and bottom halves are nodes 0 and 1. The total time is 2 minutes, and each square is a 1 second sample.
Here's the same workload after the fix:
Fix 2:
scx_rusty: compare abs values in xfer_between()
A LoadEntity gets the load to transfer between two entities by taking the minimum of their imbalances and reducing its abs value by xfer_ratio.
In practice self.imbal(), the push node or domain, always has positive imbalance and other.imbal(), the pull node or domain, always has negative imbalance, so other.imbal() is always the minimum even though the abs value of its imbalance might be greater than the abs value of self.imbal(). It seems like the intent is to take the minimum of the two absolute values instead to avoid overbalancing at the puller, so make both values abs.