You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Fix race conditions in differential evolution (#1063)
Through a combination of silly mistakes, I missed a pile of race conditions in the OpenMP threading.
Switch to C++ threading. Note that this change requires serial generation of trial vectors.
Hopefully I can figure out to parallelize the generation of trial vectors to reduce the serial section a la Ahmdahl's law,
while simultaneously keeping thread sanitizer happy.
using Real = typename ArgumentContainer::value_type;
19
19
ArgumentContainer lower_bounds;
20
20
ArgumentContainer upper_bounds;
21
-
Real F = static_cast<Real>(0.65);
22
-
double crossover_ratio = 0.5;
21
+
Real mutation_factor = static_cast<Real>(0.65);
22
+
double crossover_probability = 0.5;
23
23
// Population in each generation:
24
24
size_t NP = 200;
25
25
size_t max_generations = 1000;
@@ -47,8 +47,8 @@ We justify this design choice by reference to the "No free lunch" theorem of Wol
47
47
48
48
`lower_bounds`: A container representing the lower bounds of the optimization space along each dimension. The `.size()` of the bounds should return the dimension of the problem.
49
49
`upper_bounds`: A container representing the upper bounds of the optimization space along each dimension. It should have the same size of `lower_bounds`, and each element should be >= the corresponding element of `lower_bounds`.
50
-
`F`: The scale factor controlling the rate at which the population evolves (default is 0.65).
51
-
`crossover_ratio`: The crossover ratio determining the trade-off between exploration and exploitation (default is 0.5).
50
+
`mutation_factor`: The F or scale factor controlling the rate at which the population evolves (default is 0.65).
51
+
`crossover_probability`: The crossover probability determining the trade-off between exploration and exploitation (default is 0.5).
52
52
`NP`: The population size (default is 200). Parallelization occurs over the population, so this should be "large".
53
53
`max_generations`: The maximum number of generations for the optimization (default is 1000).
54
54
`threads`: The number of threads to use for parallelization (default is the hardware concurrency). If the objective function is already multithreaded, then this should be set to 1 to prevent oversubscription.
@@ -64,7 +64,7 @@ The most robust way of decreasing the probability of getting stuck in a local mi
64
64
template <typename ArgumentContainer, class Func, class URBG>
@@ -102,6 +102,12 @@ Supported termination criteria are explicit requests for termination, value-to-r
102
102
Price, Storn, and Lampinen, Section 2.8 also list population statistics and lack of accepted trials over many generations as sensible termination criteria.
103
103
These could be supported if there is demand.
104
104
105
+
Parallelization with `std::thread` does have overhead-especially for very fast function calls.
106
+
We found that the function call needs to be roughly a microsecond for unambigous parallelization wins.
107
+
However, we have not provided conditional parallelization as computationally inexpensive cost functions are the exception; not the rule.
108
+
If there is a clear use case for conditional parallelization (cheap cost function in very high dimensions is a good example),
109
+
we can provide it.
110
+
105
111
[h4:references References]
106
112
107
113
* Price, Kenneth, Rainer M. Storn, and Jouni A. Lampinen. ['Differential evolution: a practical approach to global optimization.] Springer Science & Business Media, 2006.
0 commit comments