Skip to content

Commit 4003fbb

Browse files
committed
Solved mutithread issue and bumped v0.12.6
There were an issue on multithreaded code that would have crashed when the number of interactive threads would have been set >1 (from command line). This commit correctly account for whatever the number of interactive threads is.
1 parent 3265189 commit 4003fbb

5 files changed

Lines changed: 12 additions & 12 deletions

File tree

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "BetaML"
22
uuid = "024491cd-cc6b-443e-8034-08ea7eb7db2b"
33
authors = ["Antonello Lobianco <antonello@lobianco.org>"]
4-
version = "0.12.5"
4+
version = "0.12.6"
55

66
[deps]
77
AbstractTrees = "1520ce14-60c1-5f80-bbc7-55ef81b5835c"

src/Trees/RandomForests.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,11 +224,11 @@ function buildForest(x, y::AbstractArray{Ty,1}, n_trees=30; max_depth = size(x,1
224224
end
225225

226226
masterSeed = rand(rng,100:Int(floor(typemax(Int64)/10000))) # Some RNG have problems with very small seed. Also, the master seed has to be computed _before_ generate_parallel_rngs
227-
rngs = generate_parallel_rngs(rng,Threads.nthreads()+1)
227+
rngs = generate_parallel_rngs(rng,Threads.nthreads())
228228

229229
#for i in 1:n_trees # for easier debugging/profiling...
230230
Threads.@threads for i in 1:n_trees
231-
tsrng = rngs[Threads.threadid()] # Thread safe random number generator
231+
tsrng = rngs[Threads.threadid()-Threads.nthreads(:interactive)] # Thread safe random number generator
232232
Random.seed!(tsrng,masterSeed+i*10)
233233
toSample = rand(tsrng, 1:N, Int(round(N*sampling_share)))
234234
notToSample = setdiff(1:N,toSample)

src/Utils/Processing.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1223,11 +1223,11 @@ function tune!(m,method::GridSearch,data)
12231223
subs = partition([data...],[res_share,1-res_share],rng=rng, copy=true)
12241224
sampleddata = (collect([subs[i][1] for i in 1:length(subs)])...,)
12251225
masterSeed = rand(rng,100:typemax(Int64))
1226-
rngs = generate_parallel_rngs(rng,Threads.nthreads()+1)
1226+
rngs = generate_parallel_rngs(rng,Threads.nthreads())
12271227
n_candidates = length(candidates)
12281228
@threadsif multithreads for c in 1:n_candidates
12291229
candidate = candidates[c]
1230-
tsrng = rngs[Threads.threadid()]
1230+
tsrng = rngs[Threads.threadid()-Threads.nthreads(:interactive)]
12311231
Random.seed!(tsrng,masterSeed+c*10)
12321232
options(m).verbosity == FULL && println("Testing candidate $candidate")
12331233
mc = deepcopy(m)
@@ -1285,12 +1285,12 @@ function tune!(m,method::SuccessiveHalvingSearch,data)
12851285
options(m).verbosity >= STD && println("(e $e / $epochs) N data / n candidates / n candidates to retain : $(n_orig * res_share) \t $ncandidates_thisepoch $ncandidates_tokeep")
12861286
scores = Vector{Tuple{Float64,Dict}}(undef,ncandidates_thisepoch)
12871287
masterSeed = rand(rng,100:typemax(Int64))
1288-
rngs = generate_parallel_rngs(rng,Threads.nthreads()+1)
1288+
rngs = generate_parallel_rngs(rng,Threads.nthreads())
12891289
n_candidates = length(candidates)
12901290
ncandidates_thisepoch == n_candidates || error("Problem with number of candidates!")
12911291
@threadsif multithreads for c in 1:n_candidates
12921292
candidate=candidates[c]
1293-
tsrng = rngs[Threads.threadid()]
1293+
tsrng = rngs[Threads.threadid()-Threads.nthreads(:interactive)]
12941294
Random.seed!(tsrng,masterSeed+c*10)
12951295
options(m).verbosity == FULL && println("(e $e) Testing candidate $candidate")
12961296
mc = deepcopy(m)

src/Utils/Stochasticity.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,14 @@ For multi-threaded models, return n independent random number generators (one pe
1515
1616
Note that each ring is a _copy_ of the original random ring. This means that code that _use_ these RNGs will not change the original RNG state.
1717
18-
Use it with `rngs = generate_parallel_rngs(rng,Threads.nthreads()+1)` to have a separate rng per thread.
19-
**Attention**: the `+1` is necessary from Julia 1.12 onwards, because the main thread is counted differently.
18+
Use it with `rngs = generate_parallel_rngs(rng,Threads.nthreads()` to have a separate rng per thread.
19+
**Attention**: `Threads.threadid()` of working threads is between `Threads.nthreads(:interactive)` and `Threads.nthreads(:interactive)+Threads.nthreads(:default)`
2020
By default the function doesn't re-seed the RNG, as you may want to have a loop index based re-seeding strategy rather than a threadid-based one (to guarantee the same result independently of the number of threads).
2121
If you prefer, you can instead re-seed the RNG here (using the parameter `reSeed=true`), such that each thread has a different seed. Be aware however that the stream of number generated will depend from the number of threads at run time.
2222
"""
2323
function generate_parallel_rngs(rng::AbstractRNG, n::Integer;reSeed=false)
2424
if reSeed
25-
seeds = [rand(rng,100:18446744073709551615) for i in 1:n] # some RNGs have issues with too small seed
25+
seeds = [rand(rng,100:Int(ceil(typemax(Int64)/1000))) for i in 1:n] # some RNGs have issues with too small seed
2626
rngs = [deepcopy(rng) for i in 1:n]
2727
return Random.seed!.(rngs,seeds)
2828
else

test/Utils_tests.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -729,10 +729,10 @@ function innerFunction(bootstrappedx; rng=Random.GLOBAL_RNG)
729729
end
730730
function outerFunction(x;rng = Random.GLOBAL_RNG)
731731
masterSeed = rand(rng,100:Int(floor(typemax(Int64)/10000))) # important: with some RNG it is important to do this before the generate_parallel_rngs to guarantee independance from number of threads
732-
rngs = generate_parallel_rngs(rng,Threads.nthreads()+1) # make new copy instances
732+
rngs = generate_parallel_rngs(rng,Threads.nthreads()) # make new copy instances
733733
results = Array{Float64,1}(undef,30)
734734
Threads.@threads for i in 1:30
735-
tsrng = rngs[Threads.threadid()] # Thread safe random number generator: one RNG per thread
735+
tsrng = rngs[Threads.threadid()-Threads.nthreads(:interactive)] # Thread safe random number generator: one RNG per thread
736736
Random.seed!(tsrng,masterSeed+i*10) # But the seeding depends on the i of the loop not the thread: we get same results indipendently of the number of threads
737737
toSample = rand(tsrng, 1:100,100)
738738
bootstrappedx = x[toSample]

0 commit comments

Comments
 (0)