Skip to content

Commit 6f0f5c9

Browse files
committed
added method to Base.in
1 parent d8411bc commit 6f0f5c9

File tree

2 files changed

+83
-52
lines changed

2 files changed

+83
-52
lines changed

src/ParallelUtilities.jl

Lines changed: 54 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -130,14 +130,14 @@ function Base.iterate(p::ProductSplit,state=(first(p),1))
130130
(el,(p[n+1],n+1))
131131
end
132132

133-
@inline Base.@propagate_inbounds function _firstlastdim(p::ProductSplit{<:Any,N},dim::Int,
133+
@inline Base.@propagate_inbounds function _firstlastalongdim(p::ProductSplit{<:Any,N},dim::Int,
134134
firstindchild::Tuple=childindex(p,p.firstind),
135135
lastindchild::Tuple=childindex(p,p.lastind)) where {N}
136136

137-
_firstlastdim(p.iterators,dim,firstindchild,lastindchild)
137+
_firstlastalongdim(p.iterators,dim,firstindchild,lastindchild)
138138
end
139139

140-
@inline function _firstlastdim(iterators::NTuple{N,<:Any},dim::Int,
140+
@inline Base.@propagate_inbounds function _firstlastalongdim(iterators::NTuple{N,<:Any},dim::Int,
141141
firstindchild::Tuple,lastindchild::Tuple) where {N}
142142

143143
@boundscheck (1 <= dim <= N) || throw(BoundsError(iterators,dim))
@@ -195,7 +195,7 @@ end
195195
firstindchild = childindex(p,p.firstind)
196196
lastindchild = childindex(p,p.lastind)
197197

198-
@inbounds first_iter,last_iter = _firstlastdim(p,dim,firstindchild,lastindchild)
198+
@inbounds first_iter,last_iter = _firstlastalongdim(p,dim,firstindchild,lastindchild)
199199

200200
v = last_iter
201201

@@ -227,7 +227,7 @@ end
227227
firstindchild = childindex(p,p.firstind)
228228
lastindchild = childindex(p,p.lastind)
229229

230-
@inbounds first_iter,last_iter = _firstlastdim(p,dim,firstindchild,lastindchild)
230+
@inbounds first_iter,last_iter = _firstlastalongdim(p,dim,firstindchild,lastindchild)
231231

232232
v = first_iter
233233

@@ -262,7 +262,7 @@ end
262262
firstindchild = childindex(p,p.firstind)
263263
lastindchild = childindex(p,p.lastind)
264264

265-
@inbounds first_iter,last_iter = _firstlastdim(p,dim,firstindchild,lastindchild)
265+
@inbounds first_iter,last_iter = _firstlastalongdim(p,dim,firstindchild,lastindchild)
266266

267267
v = (first_iter,last_iter)
268268
# The last index will not roll over so this can be handled easily
@@ -278,6 +278,36 @@ end
278278
return v
279279
end
280280

281+
_infullrange(val::T,p::ProductSplit{T}) where {T} = _infullrange(val,p.iterators)
282+
283+
function _infullrange(val,t::Tuple)
284+
first(val) in first(t) && _infullrange(Base.tail(val),Base.tail(t))
285+
end
286+
_infullrange(::Tuple{},::Tuple{}) = true
287+
288+
struct OrderedTuple{T}
289+
t :: T
290+
end
291+
292+
function Base.:<=(a::OrderedTuple{T},b::OrderedTuple{T}) where {T}
293+
_le(reverse(a.t),reverse(b.t))
294+
end
295+
296+
function _le(t1::Tuple,t2::Tuple)
297+
first(t1) < first(t2) || ((first(t1) == first(t2)) & _le(Base.tail(t1),Base.tail(t2)))
298+
end
299+
_le(::Tuple{},::Tuple{}) = true
300+
301+
function Base.in(val::T,p::ProductSplit{T}) where {T}
302+
_infullrange(val,p) || return false
303+
304+
val_ot = OrderedTuple(val)
305+
first_iter = OrderedTuple(p[1])
306+
last_iter = OrderedTuple(p[end])
307+
308+
first_iter <= val_ot <= last_iter
309+
end
310+
281311
###################################################################################################
282312

283313
function worker_rank()
@@ -287,42 +317,32 @@ function worker_rank()
287317
myid()-minimum(workers())+1
288318
end
289319

290-
function split_across_processors(num_tasks::Integer,num_procs=nworkers(),proc_id=worker_rank())
291-
if num_procs == 1
292-
return num_tasks
293-
end
294-
295-
num_tasks_per_process,num_tasks_leftover = div(num_tasks,num_procs),mod(num_tasks,num_procs)
296-
297-
num_tasks_on_proc = num_tasks_per_process + (proc_id <= mod(num_tasks,num_procs) ? 1 : 0 );
298-
task_start = num_tasks_per_process*(proc_id-1) + min(num_tasks_leftover+1,proc_id);
320+
# function split_across_processors_iterators(arr₁::Base.Iterators.ProductIterator,num_procs,proc_id)
299321

300-
return task_start:(task_start+num_tasks_on_proc-1)
301-
end
322+
# @assert(proc_id<=num_procs,"processor rank has to be less than number of workers engaged")
302323

303-
function split_across_processors(arr₁::Base.Iterators.ProductIterator,num_procs=nworkers(),proc_id=worker_rank())
324+
# num_tasks = length(arr₁);
304325

305-
@assert(proc_id<=num_procs,"processor rank has to be less than number of workers engaged")
326+
# num_tasks_per_process,num_tasks_leftover = div(num_tasks,num_procs),mod(num_tasks,num_procs)
306327

307-
num_tasks = length(arr₁);
328+
# num_tasks_on_proc = num_tasks_per_process + (proc_id <= mod(num_tasks,num_procs) ? 1 : 0 );
329+
# task_start = num_tasks_per_process*(proc_id-1) + min(num_tasks_leftover,proc_id-1) + 1;
308330

309-
num_tasks_per_process,num_tasks_leftover = div(num_tasks,num_procs),mod(num_tasks,num_procs)
331+
# Iterators.take(Iterators.drop(arr₁,task_start-1),num_tasks_on_proc)
332+
# end
310333

311-
num_tasks_on_proc = num_tasks_per_process + (proc_id <= mod(num_tasks,num_procs) ? 1 : 0 );
312-
task_start = num_tasks_per_process*(proc_id-1) + min(num_tasks_leftover,proc_id-1) + 1;
334+
# function split_product_across_processors_iterators(arrs_tuple,num_procs,proc_id)
335+
# split_across_processors_iterators(Iterators.product(arrs_tuple...),num_procs,proc_id)
336+
# end
313337

314-
Iterators.take(Iterators.drop(arr₁,task_start-1),num_tasks_on_proc)
315-
end
316-
317-
function split_product_across_processors(arr₁::AbstractVector,arr₂::AbstractVector,
318-
num_procs::Integer=nworkers(),proc_id::Integer=worker_rank())
319-
# arr₁ will change faster
320-
split_across_processors(Iterators.product(arr₁,arr₂),num_procs,proc_id)
338+
function split_across_processors(num_tasks::Integer,num_procs=nworkers(),proc_id=worker_rank())
339+
split_product_across_processors((1:num_tasks,),num_procs,proc_id)
321340
end
322341

323-
function split_product_across_processors(arrs_tuple::NTuple,
342+
function split_product_across_processors(arrs_tuple::Tuple,
324343
num_procs::Integer=nworkers(),proc_id::Integer=worker_rank())
325-
return split_across_processors(Iterators.product(arrs_tuple...),num_procs,proc_id)
344+
345+
ProductSplit(arrs_tuple,num_procs,proc_id)
326346
end
327347

328348
function get_processor_id_from_split_array(arr₁::AbstractVector,arr₂::AbstractVector,
@@ -367,9 +387,9 @@ function get_processor_id_from_split_array(arr₁::AbstractVector,arr₂::Abstra
367387
return proc_id
368388
end
369389

370-
function get_processor_id_from_split_array(iter,val,num_procs)
390+
function get_processor_id_from_split_array(iterators,val,num_procs)
371391
for proc_id in 1:num_procs
372-
tasks_on_proc = split_across_processors(iter,num_procs,proc_id)
392+
tasks_on_proc = split_product_across_processors(iterators,num_procs,proc_id)
373393
if val tasks_on_proc
374394
return proc_id
375395
end

test/runtests.jl

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,6 @@
11
using ParallelUtilities,Test
22

3-
function split_across_processors(num_tasks::Integer,num_procs,proc_id)
4-
if num_procs == 1
5-
return num_tasks
6-
end
7-
8-
num_tasks_per_process,num_tasks_leftover = div(num_tasks,num_procs),mod(num_tasks,num_procs)
9-
10-
num_tasks_on_proc = num_tasks_per_process + (proc_id <= mod(num_tasks,num_procs) ? 1 : 0 );
11-
task_start = num_tasks_per_process*(proc_id-1) + min(num_tasks_leftover+1,proc_id);
12-
13-
return task_start:(task_start+num_tasks_on_proc-1)
14-
end
15-
16-
function split_across_processors(arr₁::Base.Iterators.ProductIterator,num_procs,proc_id)
3+
function split_across_processors_iterators(arr₁::Base.Iterators.ProductIterator,num_procs,proc_id)
174

185
@assert(proc_id<=num_procs,"processor rank has to be less than number of workers engaged")
196

@@ -27,19 +14,18 @@ function split_across_processors(arr₁::Base.Iterators.ProductIterator,num_proc
2714
Iterators.take(Iterators.drop(arr₁,task_start-1),num_tasks_on_proc)
2815
end
2916

30-
function split_product_across_processors(arrs_tuple,num_procs,proc_id)
31-
split_across_processors(Iterators.product(arrs_tuple...),num_procs,proc_id)
17+
function split_product_across_processors_iterators(arrs_tuple,num_procs,proc_id)
18+
split_across_processors_iterators(Iterators.product(arrs_tuple...),num_procs,proc_id)
3219
end
3320

3421

35-
3622
@testset "ProductSplit" begin
3723
@testset "Constructor" begin
3824

3925
function checkPSconstructor(iters,npmax=10)
4026
for np = 1:npmax, p = 1:np
4127
ps = ProductSplit(iters,np,p)
42-
@test collect(ps) == collect(split_product_across_processors(iters,np,p))
28+
@test collect(ps) == collect(split_product_across_processors_iterators(iters,np,p))
4329
end
4430
end
4531

@@ -85,4 +71,29 @@ end
8571
checkPSextrema(iters,fn)
8672
end
8773
end
74+
75+
@testset "in" begin
76+
77+
function checkifpresent(iters,npmax=10)
78+
for np = 1:npmax, p = 1:np
79+
ps = ProductSplit(iters,np,p)
80+
pcol = collect(ps)
81+
82+
for el in pcol
83+
# It should be contained in this iterator
84+
@test el in ps
85+
for p2 in 1:np
86+
# It should not be contained anywhere else
87+
p2 == p && continue
88+
ps2 = ProductSplit(iters,np,p2)
89+
@test !(el in ps2)
90+
end
91+
end
92+
end
93+
end
94+
95+
for iters in [(1:10,),(1:10,4:6),(1:10,4:6,1:4),(1:2:10,4:1:6)]
96+
checkifpresent(iters)
97+
end
98+
end
8899
end

0 commit comments

Comments
 (0)