Julia: Cómo copiar datos a otro procesador en Julia

¿Cómo se mueven los datos de un procesador a otro en julia?

Digamos que tengo una matriz

a = [1:10] 

O alguna otra estructura de datos. ¿Cuál es la forma correcta de ponerlo en todos los demás procesadores disponibles para que esté disponible en esos procesadores con el mismo nombre de variable?

Al principio no sabía cómo hacer esto, así que dediqué un tiempo a descifrarlo.

Aquí hay algunas funciones que escribí para pasar objetos:

sendto

Envíe un número arbitrario de variables a procesos especificados.

Se crean nuevas variables en el módulo principal en procesos especificados. El nombre será la clave del argumento de la palabra clave y el valor será el valor asociado.

 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 

Ejemplos

 # 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

Recupere un objeto definido en un módulo arbitrario en un proceso arbitrario. Se predetermina al módulo principal.

El nombre del objeto que se debe recuperar debe ser un símbolo.

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

Ejemplos

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

passobj

Pase una cantidad arbitraria de objetos de un proceso a procesos arbitrarios. La variable debe definirse en el módulo from_mod del proceso src y se copiará con el mismo nombre al módulo to_mod en cada proceso objective.

 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 

Ejemplos

 # 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) 

Para que todos aquí lo sepan, reúno estas ideas en un paquete ParallelDataTransfer.jl para esto. Entonces solo debes hacer

 using ParallelDataTransfer 

(después de la instalación) para usar las funciones mencionadas en las respuestas aquí. ¿Por qué? ¡Estas funciones son bastante útiles! Agregué algunas pruebas, algunas macros nuevas y las actualicé un poco (transmiten v0.5, fallan en v0.4.x). No dude en realizar solicitudes de extracción para editarlas y agregar más.

usa @eval @everywhere... y escapa de la variable local. Me gusta esto:

 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 

Para complementar la respuesta de @ spencerlyon2 aquí hay algunas macros:

 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 

La macro @spawnat vincula un valor a un símbolo en un proceso particular

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

La macro @broadcast vincula un valor a un símbolo en todos los procesos, excepto en 1 (como lo encontré haciendo las expresiones futuras usando el nombre copie la versión del proceso 1 )

 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