I’m implementing an algorithm in Go I’ve done in various other languages.
I’ve first done a single-threaded GO version to ensure I’ve got it working.
Now I want to do a multi-threaded version, as I’ve done with the other languages.
I’m using Go 1.16.
Below is the single-threaded Go code I needed to make multi-threaded.
sums := make([]uint, pairscnt)
lastwins := make([]uint, pairscnt)
for i, r_hi := range restwins { // sieve twinpair restracks
l, c := twins_sieve(r_hi, kmin, kmax, kb, start_num, end_num,
modpg, primes, resinvrs)
lastwins[i] = l; sums[i] = c
fmt.Printf("\r%d of %d twinpairs done", (i + 1), pairscnt)
}
Here I use a goroutine
to make it multi-threaded.
It compiles, but seems to only executes one time, and gives incorrect numerical results.
sums := make([]uint, pairscnt)
lastwins := make([]uint, pairscnt)
for i, r_hi := range restwins {
go func() {
l, c := twins_sieve(r_hi, kmin, kmax, kb, start_num, end_num,
modpg, primes, resinvrs)
lastwins[i] = l; sums[i] = c
fmt.Printf("\r%d of %d twinpairs done", (i + 1), pairscnt)
}()
}
Here’s the same (working) snippet in Crystal
, which has a similar concurrency model.
sums = Array(UInt64).new(pairscnt, 0)
lastwins = Array(UInt64).new(pairscnt, 0)
done = Channel(Nil).new(pairscnt)
restwins.each_with_index do |r_hi, i|
spawn do
lastwins[i], sums[i] = twins_sieve(r_hi, kmin, kmax, kb, start_num,
end_num, modpg, primes, resinvrs)
print "\r#{i + 1} of #{pairscnt} twinpairs done"
done.send(nil)
end end
pairscnt.times { done.receive }
Here’s the Rust snippet, which does true parallel execution, and is fastest of all versions.
let (lastwins, sums): (Vec<_>, Vec<_>) = {
let counter = RelaxedCounter::new();
restwins.par_iter().map( |r_hi| {
let out = twins_sieve(*r_hi, kmin, kmax, kb, start_num, end_num,
modpg, &primes.to_vec(), &resinvrs);
print!("\r{} of {} twinpairs done", counter.increment(), pairscnt);
out
}).unzip()
};
I hope a Go guru can tell me what I need to do to get the code to execute correctly.