2014-12-28 12 views
24

Verileri bir işlemciden diğerine nasıl aktarırsınız? Julia: Verileri başka bir işlemciye kopyalamak için: Julia

Bir dizi

a = [1:10] 

ya da başka bir veri yapısı olduğunu varsayalım. Diğer tüm mevcut işlemcilere koymanın uygun yolu nedir, böylece bu değişkenler aynı değişken adıyla kullanılabilir olacak mı?

+1

Bu oldukça standart bir istek olması gerektiği gibi görünüyor mu? – bdeonovic

+0

Belgelerinizi okumak için bir öneride bulunabilirsiniz: http://julia.readthedocs.org/en/latest/manual/parallel-computing/ @everywhere makronuzu aradığınız şey nedir? –

+0

Ben dokümanı okudum ve @everywhere bunu yapmaz – bdeonovic

cevap

30

İlk başta bunu nasıl yapacağımı bilmiyordum, bu yüzden biraz zaman geçirdim.

İşte nesneleri geçmek yazdığı bazı işlevler şunlardır:

sendto

belirtilen işlemlere değişkenlerin isteğe bağlı sayıda gönder.

Belirtilen işlemlerde Ana modülde yeni değişkenler oluşturulur. adı, anahtar kelime bağımsız değişkeninin anahtarı olacaktır ve değer, ilişkili değeri olacaktır.

function sendto(p::Int; args...) 
    for (nm, val) in args 
     @spawnat(p, eval(Main, Expr(:(=), nm, val))) 
    end 
end 


function sendto(ps::Vector{Int}; args...) 
    for p in ps 
     sendto(p; args...) 
    end 
end 

örnekleri
# creates an integer x and Matrix y on processes 1 and 2 
sendto([1, 2], x=100, y=rand(2, 3)) 

# create a variable here, then send it everywhere else 
z = randn(10, 10); sendto(workers(), z=z) 

getfrom

keyfi sürece keyfi bir modülde tanımlanan bir nesne alma. Ana modülün varsayılanları.

Alınacak nesnenin adı bir sembol olmalıdır.

getfrom(p::Int, nm::Symbol; mod=Main) = fetch(@spawnat(p, getfield(mod, nm))) 

örnekleri
# get an object from named x from Main module on process 2. Name it x 
x = getfrom(2, :x) 

passobj

işlemleri keyfi bir işlemden nesneleri rasgele sayıda geçirin. Değişken, src işleminin from_mod modülünde tanımlanmalı ve her bir hedef işlem için aynı ad altında to_mod modülüne kopyalanacaktır.spencerlyon2 'ın cevabı @ tamamlamak için

function passobj(src::Int, target::Vector{Int}, nm::Symbol; 
       from_mod=Main, to_mod=Main) 
    r = RemoteRef(src) 
    @spawnat(src, put!(r, getfield(from_mod, nm))) 
    for to in target 
     @spawnat(to, eval(to_mod, Expr(:(=), nm, fetch(r)))) 
    end 
    nothing 
end 


function passobj(src::Int, target::Int, nm::Symbol; from_mod=Main, to_mod=Main) 
    passobj(src, [target], nm; from_mod=from_mod, to_mod=to_mod) 
end 


function passobj(src::Int, target, nms::Vector{Symbol}; 
       from_mod=Main, to_mod=Main) 
    for nm in nms 
     passobj(src, target, nm; from_mod=from_mod, to_mod=to_mod) 
    end 
end 

Örnekler

# pass variable named x from process 2 to all other processes 
passobj(2, filter(x->x!=2, procs()), :x) 

# pass variables t, u, v from process 3 to process 1 
passobj(3, 1, [:t, :u, :v]) 

# Pass a variable from the `Foo` module on process 1 to Main on workers 
passobj(1, workers(), [:foo]; from_mod=Foo) 
+0

Tam olarak aradığım şey budur. @spawnat (p, eval (Main, Expr (: (=), nm, val))). – conjectures

+0

Awesome, bu sizin için çalışıyor, makrolar için teşekkürler – spencerlyon2

+0

Bu makrolar bir paket veya hatta Julia'nın bir parçası haline gelmesi çok yararlı! – user1438310

0

burada bazı makrolardır:

function sendtosimple(p::Int, nm, val) 
    ref = @spawnat(p, eval(Main, Expr(:(=), nm, val))) 
end 

macro sendto(p, nm, val) 
    return :(sendtosimple($p, $nm, $val)) 
end 

macro broadcast(nm, val) 
    quote 
    @sync for p in workers() 
     @async sendtosimple(p, $nm, $val) 
    end 
    end 
end 

@spawnat makro belirli bir süreci üzerinde sembole bir değer bağlar

julia> @sendto 2 :bip pi/3 
RemoteRef{Channel{Any}}(9,1,5340) 

julia> @fetchfrom 2 bip 
1.0471975511965976 
julia> @broadcast :bozo 5 

julia> @fetchfrom 2 bozo 
5 

julia> bozo 
ERROR: UndefVarError: bozo not defined 

julia> bozo = 3    #these three lines are why I exclude pid 1 
3 

julia> @fetchfrom 7 bozo 
3 

julia> @fetchfrom 7 Main.bozo 
5 
6

kullanımını @eval @everywhere... (I adı sürecinin 1 gelen sürümünü kopyalamak kullanarak bunu yaptı gelecekteki ifadeleri yapıyor bulundu gibi) ve yerel değişken kaçış @broadcast makro 1 hariç tüm süreçlerde bir sembole bir değer bağlar. Böyle:

julia> a=collect(1:3) 
3-element Array{Int64,1}: 
    1 
    2 
    3 

julia> addprocs(1) 
1-element Array{Int64,1}: 
2 

julia> @eval @everywhere a=$a 

julia> @fetchfrom 2 a 
3-element Array{Int64,1}: 
1 
2 
3 
+0

Çok basit bir çözüm, güzel. – esel

7

Sadece bunun için bir paket ParallelDataTransfer.jl bir araya bu fikirleri koymak, burada herkesin bildiği bu yüzden. Bu nedenle, burada cevaplarda belirtilen işlevleri kullanmak için

(kurulduktan sonra) yapmanız yeterlidir. Niye ya? Bu işlevler oldukça kullanışlıdır! Bazı testler, bazı yeni makrolar ekledim ve onları biraz güncelledim (v0.5'ten geçiyorlar, v0.4.x üzerinde başarısız oluyorlar). Bunları düzenlemek ve daha fazlasını eklemek için çekme isteklerinde bulunabilirsiniz.