What is the best way to parallel my evaluation step of the genetic algorithm? I.e. would like to parallel the following code.
function test_func(pop::Pop, extra_data::Dict)::Pop
for i in 1:pop.num_size
pop.obj_func[i, :f1] = (4*pop.individuals[i].parms[1][1]*pop.individuals[i].parms[1][1])+(4*pop.individuals[i].parms[2][1]*pop.individuals[i].parms[2][1])
pop.obj_func[i, :f2] = ((pop.individuals[i].parms[1][1]-5)*(pop.individuals[i].parms[1][1]-5))+((pop.individuals[i].parms[2][1]-5)*(pop.individuals[i].parms[2][1]-5))
end
return pop
end
mutable struct Pop
num_size::Int64
individuals::Array{Ind,1}
obj_func::DataFrame
end
mutable struct Ind
parms::Array{Array{Number,2},1}
end
I already have done it and it didn´t lead to an error, but I´m not sure if it is thread safe, because I read in some topics that not all types are thread safe.
How do I know that it works correctly or not? Just by comparing the result of the parallel executed loop with the serial executed loop? Can I just store the data first in a simple array and than copy it after the for-loop to the dataframe pop.obj_func. Have I also consider the reading part? Let´s say my evaluation function is a bit more complicated. I.e. I have a mutable struct, which is a temporary variable, changes in every loop, is depended on the pop.individuals[i].parms[1] and necessary to calculate the objective functions.
function test_func(pop::Pop, extra_data::Dict)::Pop
for i in 1:pop.num_size
my_struct = MyStruct.create(pop.individuals[i].parms[1], extra_data)
pop.obj_func[i, :f1] = calculate_f1(my_struct)
pop.obj_func[i, :f2] = calculate_f2(my_struct)
end
return pop
end