Параллельное программирование Julia - Предоставление существующей функции всем работникам
Я столкнулся со следующей проблемой:
У меня есть функция с именем TrainModel, которая работает очень долго в одном потоке. Когда он заканчивает вычисления, он возвращает функцию в качестве выходного аргумента, пусть назовет ее f. Когда я задаю тип этого f, Джулия возвращает:
(общая функция с 1 методом)
(я не уверен, что эта последняя информация полезна для всех, кто это читает)
Теперь на втором этапе мне нужно применить функцию f к очень большому массиву значений. Это шаг, который я хотел бы распараллелить. Запустив Julia с несколькими процессами, например
julia -p 4
в идеале я бы использовал:
pmap(f, my_values)
или, возможно:
aux = @parallel (hcat) for ii=1:100000000
f(my_values[ii])
end
К сожалению, это не работает. Юлия жалуется, что работники не знают о функции f, то есть я получаю сообщение:
ОШИБКА: функция f не определена в процессе 2
Как я могу сделать функцию f доступной для всех работников? Очевидно, что "грязным" решением будет выполнение отнимающей много времени функции TrainModel для всех рабочих, например, это возможно:
@everywhere f = TrainModel( ... )
но это будет пустой тратой процессора, когда все, что я хочу, это то, что только результат f доступен всем работникам.
Хотя я искал сообщения с похожими проблемами, до сих пор я не мог найти ответ...
Спасибо заранее!
лучше,
Н.
Ответы
Ответ 1
Подход к возврату функции кажется элегантным, но, к сожалению, в отличие от JavaScript, Julia не решает все переменные при создании функций.
Технически ваша обучающая функция может генерировать исходный код функции с буквальными значениями для всех подготовленных параметров. Затем передайте его каждому рабочему процессу, который может анализировать его в своей среде на вызываемую функцию.
Я предлагаю вернуть структуру данных, которая содержит всю информацию для создания обучаемой функции: веса ANN, векторов поддержки, правил принятия решений...
Определите "обученную" функцию для рабочих процессов, чтобы она использовала подготовленные параметры. Возможно, вы захотите иметь возможность сохранять результаты обучения на диске в любом случае, чтобы вы могли легко перепрограммировать свои вычисления.
Ответ 2
Существует решение, основанное на Unix, основанное на пакете PTools.jl(https://github.com/amitmurthy/PTools.jl).
Он полагается на parallelism через forking вместо встроенного механизма Julia. Формованные процессы порождаются с тем же рабочим пространством, что и основной процесс, поэтому все функции и переменные доступны непосредственно работникам.
Это похоже на кластеры Fork в R параллельном пакете, поэтому его можно использовать как функцию mclapply.
Интересующей функцией является pfork (n:: Integer, f:: Function, args...) и одна заметная разница с mclapply в R состоит в том, что функция f должна принимать в качестве первого аргумента индекс рабочего.
Пример:
Pkg.add("PTools")
Pkg.checkout("PTools") #to get the last version, else the package does not build at the time of writing
using PTools
f(workid,x) = x[workid] + 1
pfork(3, f, [1,2,3,4,5]) #Only the three first elements of the array will be computed
3-element Array{Any,1}:
2
3
4
Я ожидаю, что интерфейс для pfork будет построен таким образом, что первый аргумент функции не обязательно будет индексом рабочего, но пока он может быть использован для решения проблемы.