Я бы очень признателен за помощь в распараллеливании следующего псевдокода в Julia (и я заранее извиняюсь за длинный пост):
P, Q # both K by N matrix, K = num features and N = num samples
X, Y # K*4 by N and K*2 by N matrices
tempX, tempY # column vectors of size K*4 and K*2
ndata # a dict from parsing a .m file to be used by a solver with JuMP and Ipopt
# serial version
for i = 1:N
ndata[P] = P[:, i] # technically requires a for loop from 1 to K since the dict has to be indexed element-wise
ndata[Q] = Q[:, i]
ndata_A = run_solver_A(ndata) # with a third-party package and JuMP, Ipopt
ndata_B = run_solver_B(ndata)
kX = 1, kY = 1
for j = 1:K
tempX[kX:kX+3] = [ndata_A[j][a], ndata_A[j][b], P[j, i], Q[j, i]]
tempY[kY:kY+1] = [ndata_B[j][a], ndata_B[j][b]]
kX += 4
kY += 2
end
X[:, i] = deepcopy(tempX)
Y[:, i] = deepcopy(tempY)
end
Очевидно, что этот цикл for
может выполняться независимо, если нет доступа к столбцам P
и Q
дважды и один и тот же столбец i
из P
и Q
доступен при время. Единственное, с чем мне нужно быть осторожным, это то, что столбцы i
из X
и Y
являются правильными парами tempX
и tempY
, и меня не волнует, действительно ли i = 1, ..., N порядок поддерживается (надеюсь, это имеет смысл!).
Я прочитал официальную документацию и некоторые онлайн-уроки и написал следующее с @spawn
и fetch
, который работает для вставной части, заменив ndata[j][a]
и т. Д. На номера заполнителей 1.0 и 180:
using Distributed
addprocs(2)
num_proc = nprocs()
@everywhere function insertPQ(P, Q)
println(myid())
data = zeros(4*length(P))
k = 1
for i = 1:length(P)
data[k:k+3] = [1.0, 180., P[i], Q[i]]
k += 4
end
return data
end
P = [0.99, 0.99, 0.99, 0.99]
Q = [-0.01, -0.01, -0.01, -0.01]
for i = 1:5 # should be 4 x 32
global P = hcat(P, (P .- 0.01))
global Q = hcat(Q, (Q .- 0.01))
end
datas = zeros(16, 0) # serial result
datap = zeros(16, 32) # parallel result
@time for i = 1:32
s = fetch(@spawn insertPQ(P[:, i], Q[:, i]))
global datap = hcat(datap, s)
end
@time for i = 1:32
k = 1
for j = 1:4
datas[k:k+3, i] = [1.0, 180., P[j, i], Q[j, i]]
k += 4
end
end
println(datap == datas)
Приведенный выше код в порядке, но я заметил, что вывод был последовательно рабочий 2-> 3-> 4-> 5-> 2 ... и был намного медленнее, чем последовательный случай (я тестирую это на своем ноутбуке только с 4 ядрами, но в конечном итоге я буду запускать его на кластере). Потребовалось целую вечность для запуска при добавлении в run_solver_A/B
в insertPQ()
, что мне пришлось остановить его.
Что касается pmap()
, я не мог понять, как передать весь вектор в функцию. Я, вероятно, неправильно понял документацию, но «Преобразование коллекции c путем применения f к каждому элементу с использованием доступных рабочих и задач» звучит так, как будто я могу сделать это только поэлементно? Этого не может быть. На прошлой неделе я пошел на вступительное занятие Джулии и спросил об этом лектора. Он сказал, что я должен использовать pmap
, и с тех пор я пытаюсь заставить его работать.
Итак, как я могу распараллелить мой исходный псевдокод? Любая помощь или предложение с благодарностью!