Подтвердить что ты не робот

Julia: Как скопировать данные на другой процессор в Julia

Как вы перемещаете данные с одного процессора на другой в julia?

Скажем, у меня есть массив

a = [1:10]

Или какая-либо другая структура данных. Каков правильный способ разместить его на всех других доступных процессорах, чтобы он был доступен на этих процессорах как одно и то же имя переменной?

4b9b3361

Ответ 1

Я не знал, как это сделать сначала, поэтому я потратил некоторое время на это.

Вот некоторые функции, которые я написал для передачи объектов:

sendto

Отправить произвольное количество переменных указанным процессам.

В основном модуле для определенных процессов создаются новые переменные. имя будет ключевым аргументом ключевого слова, и значение будет связанное значение.

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

Примеры

# 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

Получить объект, определенный в произвольном модуле на произвольном обработать. По умолчанию используется основной модуль.

Имя подлежащего извлечению объекта должно быть символом.

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

Примеры

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

passobj

Передайте произвольное количество объектов из одного процесса в произвольное процессы. Переменная должна быть определена в модуле from_mod src и будет скопирован под тем же именем в to_mod модуль для каждого целевого процесса.

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

Примеры

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

Ответ 2

Просто, чтобы все знали, я объединил эти идеи в пакет ParallelDataTransfer.jl. Так что вам просто нужно сделать

using ParallelDataTransfer

(после установки), чтобы использовать функции, упомянутые в ответах здесь. Зачем? Эти функции очень полезны! Я добавил несколько тестов, некоторые новые макросы и немного обновил их (они проходят на v0.5, fail на v0.4.x). Не стесняйтесь прикладывать запросы на удаление, чтобы редактировать их и добавлять больше.

Ответ 3

используйте @eval @everywhere... и удалите локальную переменную. например:

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

Ответ 4

Чтобы добавить @spencerlyon2 ответ, вот несколько макросов:

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 связывает значение с символом в конкретном процессе

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

julia> @fetchfrom 2 bip
1.0471975511965976

Макрос @broadcast связывает значение с символом во всех процессах, кроме 1 (поскольку, как я выяснил, это сделало будущие выражения, используя имя, скопируйте версию из процесса 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