2014-12-28 7 views
24

Wie bewegen Sie Daten von einem Prozessor zum anderen in Julia?Julia: Wie kopiert man Daten auf einen anderen Prozessor in Julia

Say I ein Array

a = [1:10] 

oder eine andere Datenstruktur aufweisen. Was ist der richtige Weg, um es auf alle anderen verfügbaren Prozessoren zu setzen, damit es auf diesen Prozessoren als derselbe Variablenname verfügbar ist?

+1

Dies scheint, als sollte es eine ziemlich standard Anfrage sein nein? – bdeonovic

+0

Vielleicht erhalten Sie einen Vorschlag, um die Dokumentation zu lesen: http://julia.readthedocs.org/en/latest/manual/parallel-computing/ Ist das @ Everywhere-Makro, was Sie suchen? –

+0

Ich habe das Dokument gelesen und kein @everywhere macht das nicht – bdeonovic

Antwort

30

Ich wusste nicht, wie ich das zuerst machen sollte, also verbrachte ich einige Zeit damit, es herauszufinden.

Hier sind einige Funktionen, die ich schrieb Objekte weitergeben müssen:

sendto

eine beliebige Anzahl von Variablen auf bestimmte Prozesse senden.

Neue Variablen werden im Hauptmodul für bestimmte Prozesse erstellt. Der Name ist der Schlüssel des Schlüsselwortarguments und der Wert ist der zugehörige Wert .

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 

Beispiele

# 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

ein Objekt in einem beliebigen Modul auf einem beliebigen Prozess definiert Abrufen. Standardmäßig auf das Hauptmodul eingestellt.

Der Name des abzurufenden Objekts sollte ein Symbol sein.

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

Beispiele

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

passobj

Pass, eine beliebige Anzahl von Objekten von einem Prozess Prozesse beliebig. Die Variable muss im Modul from_mod des Prozesses src definiert sein und wird unter demselben Namen in das Modul to_mod für jeden Zielprozess kopiert.

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 

Beispiele

# 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

Dies ist genau das, was ich suchte nach @spawnat (p, eval (Main, Ausdruck (: (=), nm, val))). – conjectures

+0

Super, froh, dass es für dich funktioniert, danke für die Makros – spencerlyon2

+0

Diese Makros sind so nützlich, dass sie ein Paket oder sogar ein Teil von Julia werden sollten! – user1438310

0

hier ergänzen @ Antwort spencerlyon2 ‚s sind einige Makros:

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 

Das @spawnat Makro auf einem bestimmten Prozess

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

julia> @fetchfrom 2 bip 
1.0471975511965976 

Das @broadcast Makro bindet an ein Symbol, das einen Wert in allen Prozessen außer 1 (wie ich so gemacht Zukunft Ausdrücke tun fand den Namen kopieren Sie die Version aus dem Prozess 1 mit)

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

Verwendung @eval @everywhere... und die Flucht der lokalen Variablen. wie folgt aus:

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

Eine sehr einfache Lösung, cool. – esel

7

Nur damit jeder hier weiß, ich habe diese Ideen zusammen in einem Paket ParallelDataTransfer.jl dafür. Sie müssen also nur

using ParallelDataTransfer 

(nach der Installation), um die Funktionen in den Antworten erwähnt hier zu tun. Warum? Diese Funktionen sind sehr nützlich! Ich habe einige Tests, einige neue Makros hinzugefügt und sie ein wenig aktualisiert (sie geben v0.5 weiter, fail on v0.4.x). Fühlen Sie sich frei, Pull-Requests einzugeben, um diese zu bearbeiten und weitere hinzuzufügen.