Blender V5.0
work_balancer.cpp
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
6
7#include "util/math_base.h"
8
10
12{
13 const int num_infos = work_balance_infos.size();
14
15 if (num_infos == 1) {
16 work_balance_infos[0].weight = 1.0;
17 return;
18 }
19 if (num_infos == 0) {
20 return;
21 }
22
23 /* There is no statistics available, so start with an equal distribution. */
24 const double weight = 1.0 / num_infos;
25 for (WorkBalanceInfo &balance_info : work_balance_infos) {
26 balance_info.weight = weight;
27 }
28}
29
30static double calculate_total_time(const vector<WorkBalanceInfo> &work_balance_infos)
31{
32 double total_time = 0;
33 for (const WorkBalanceInfo &info : work_balance_infos) {
34 total_time += info.time_spent;
35 }
36 return total_time;
37}
38
39/* The balance is based on equalizing time which devices spent performing a task. Assume that
40 * average of the observed times is usable for estimating whether more or less work is to be
41 * scheduled, and how difference in the work scheduling is needed. */
42
44{
45 const int num_infos = work_balance_infos.size();
46
47 const double total_time = calculate_total_time(work_balance_infos);
48 const double time_average = total_time / num_infos;
49
50 double total_weight = 0;
51 vector<double> new_weights;
52 new_weights.reserve(num_infos);
53
54 /* Equalize the overall average time. This means that we don't make it so every work will perform
55 * amount of work based on the current average, but that after the weights changes the time will
56 * equalize.
57 * Can think of it that if one of the devices is 10% faster than another, then one device needs
58 * to do 5% less of the current work, and another needs to do 5% more. */
59 const double lerp_weight = 1.0 / num_infos;
60
61 bool has_big_difference = false;
62
63 for (const WorkBalanceInfo &info : work_balance_infos) {
64 const double time_target = mix(info.time_spent, time_average, lerp_weight);
65 const double new_weight = info.weight * time_target / info.time_spent;
66 new_weights.push_back(new_weight);
67 total_weight += new_weight;
68
69 if (std::fabs(1.0 - time_target / time_average) > 0.02) {
70 has_big_difference = true;
71 }
72 }
73
74 if (!has_big_difference) {
75 return false;
76 }
77
78 const double total_weight_inv = 1.0 / total_weight;
79 for (int i = 0; i < num_infos; ++i) {
80 WorkBalanceInfo &info = work_balance_infos[i];
81 info.weight = new_weights[i] * total_weight_inv;
82 info.time_spent = 0;
83 }
84
85 return true;
86}
87
#define CCL_NAMESPACE_END
#define mix
i
Definition text_draw.cc:230
double total_time
CCL_NAMESPACE_BEGIN void work_balance_do_initial(vector< WorkBalanceInfo > &work_balance_infos)
bool work_balance_do_rebalance(vector< WorkBalanceInfo > &work_balance_infos)
static double calculate_total_time(const vector< WorkBalanceInfo > &work_balance_infos)