Soru, "utandırıcı bir şekilde paralel" arama görevleri yapmak için temel bir model gibi görünüyor. @parallel for
yapısı bölümleme işi için iyidir, ancak tek işlem akışında for
olarak durdurmak için break
kısa devre mantığına sahip değildir.
Julia'da bunun nasıl yapılacağını göstermek için, birkaç tekerlekle kombinasyon kilidinin kombinasyonunu bulma konusunda bir oyuncak problemi düşünün. Bir tekerleğin her ayarı, bazı yöntemlerle (combodelay
zamanını alarak - aşağıdaki kodlara bakın) doğruluk açısından kontrol edilebilir. Bir tekerlek için doğru numara bulunduğunda, sonraki tekerlek aranır. Yüksek düzeyde sözde kod, OP sorusunda verilen snippet gibidir.
Bunu yapmak için aşağıdaki kod çalışıyor (0,5 ve 0,6). Bazı yorumlar ayrıntıları açıklar ve kolay kesme ve yapıştırma için kod tek bir yığın halinde verilir.
# combination lock problem parameters
const wheel_max = 1000 # size of wheel
@everywhere const magic_number = [55,10,993] # secret combination
const wheel_count = length(magic_number) # number of wheels
const combodelay = 0.01 # delay time to check single combination
# parallel short-circuit parameters
const check_to_work_ratio = 160 # ratio to limit short-circuit overhead
function find_combo(wheel,combo=Int[])
done = SharedArray{Int}(1) # shared variable to hold if and what combo
done[1] = 0 # succeded. 0 means not found yet
# setup counters to limit parallel overhead
@sync begin
@everywhere global localdone = false
@everywhere global checktime = 0.0
@everywhere global worktime = 0.0
end
# do the parallel work
@sync @parallel for i in 1:wheel_max
global localdone
global checktime
global worktime
# if not checking too much, look at shared variable
if !localdone && check_to_work_ratio*checktime < worktime
tic()
localdone = done[1]>0
checktime += toq()
end
# if no process found combo, check another combo
if !localdone
tic()
sleep(combodelay) # simulated work delay, {..statement..} from OP
if i==magic_number[wheel] # {condition} from OP
done[1] = i
localdone = true
end
worktime += toq()
else
break
end
end
if done[1]>0 # check if shared variable indicates combo for wheel found
push!(combo,done[1])
return wheel<wheel_count ? find_combo(wheel+1,combo) : (combo,true)
else
return (combo,false)
end
end
function find_combo_noparallel(wheel,combo=Int[])
found = false
i = 0
for i in 1:wheel_max
sleep(combodelay)
if i==magic_number[wheel]
found = true
break
end
end
if found
push!(combo,i)
return wheel<wheel_count ?
find_combo_noparallel(wheel+1,combo) : (combo,true)
else
return (combo,false)
end
end
function find_combo_nostop(wheel,combo=Int[])
done = SharedArray{Int}(1)
done[1] = 0
@sync @parallel for i in 1:wheel_max
sleep(combodelay)
if i==magic_number[wheel]
done[1] = i
end
end
if done[1]>0
push!(combo,done[1])
return wheel<wheel_count ?
find_combo_nostop(wheel+1,combo) : (combo,true)
else
return (combo,false)
end
end
result = find_combo(1)
println("parallel with short-circuit stopping: $result")
@assert result == (magic_number, true)
result = find_combo_noparallel(1)
println("single process with short-circuit stopping: $result")
@assert result == (magic_number, true)
result = find_combo_nostop(1)
println("parallel without short-circuit stopping: $result")
@assert result == (magic_number, true)
println("\ntimings")
print("parallel with short-circuit stopping ")
@time find_combo(1);
print("single process with short-circuit stopping ")
@time find_combo_noparallel(1)
print("parallel without short-circuit stopping ")
@time find_combo_nostop(1)
nothing
Daha iyi görünen uygulamalar olabilir ve bazı meta programlama, bazı kısa devre makinelerini gizleyebilir. Ama bu bir başlangıç olarak iyi olmalı.
Sonuçlar aşağıdaki gibi yaklaşık görünmelidir:
parallel with short-circuit stopping: ([55,10,993],true)
single process with short-circuit stopping: ([55,10,993],true)
parallel without short-circuit stopping: ([55,10,993],true)
timings
parallel with short-circuit stopping 4.473687 seconds
single process with short-circuit stopping 11.963329 seconds
parallel without short-circuit stopping 11.316780 seconds
bu 3 işçi süreçleri ile gösteri için hesaplanır. Gerçek problemler, süreç başına çok daha fazla süreç ve daha fazla işe sahip olmalı ve kısa devre yapmanın yararları açık olacaktır.