Я пытаюсь ускорить заполнение матрицы для задачи динамического программирования в Julia (v0.6.0), и я не могу получить дополнительную скорость от использования pmap
. Это связано с вопросом, который я написал почти год назад: Заполнение матрицы с помощью параллельной обработки в Julia . Тогда я смог ускорить последовательную обработку с некоторой большой помощью, и теперь я пытаюсь получить дополнительную скорость от инструментов параллельной обработки в Юлии.
Для случая последовательной обработки я использовал 3-мерную матрицу (по сути, набор матриц одинакового размера, проиндексированных по 1-му измерению) и выполнял итерации по 1-му измерению. Я хотел дать pmap
попытку, однако, более эффективно выполнять итерации по набору матриц.
Вот настройка кода. Чтобы использовать pmap
с функцией v_iter
, приведенной ниже, я преобразовал трехмерную матрицу в объект словаря с ключами словаря, равными значениям индекса в 1-м измерении (v_dict
в приведенном ниже коде, с gcc
равен размеру 1-го измерения). Функция v_iter
принимает другие объекты словаря (E_opt_dict
и gridpoint_m_dict
ниже) в качестве дополнительных входных данных:
function v_iter(a,b,c)
diff_v = 1
while diff_v>convcrit
diff_v = -Inf
#These lines efficiently multiply the value function by the Markov transition matrix, using the A_mul_B function
exp_v = zeros(Float64,gkpc,1)
A_mul_B!(exp_v,a[1:gkpc,:],Zprob[1,:])
for j=2:gz
temp=Array{Float64}(gkpc,1)
A_mul_B!(temp,a[(j-1)*gkpc+1:(j-1)*gkpc+gkpc,:],Zprob[j,:])
exp_v=hcat(exp_v,temp)
end
#This tries to find the optimal value of v
for h=1:gm
for j=1:gz
oldv = a[h,j]
newv = (1-tau)*b[h,j]+beta*exp_v[c[h,j],j]
a[h,j] = newv
diff_v = max(diff_v, oldv-newv, newv-oldv)
end
end
end
end
gz = 9
gp = 13
gk = 17
gcc = 5
gm = gk * gp * gcc * gz
gkpc = gk * gp * gcc
gkp = gk*gp
beta = ((1+0.015)^(-1))
tau = 0.35
Zprob = [0.43 0.38 0.15 0.03 0.00 0.00 0.00 0.00 0.00; 0.05 0.47 0.35 0.11 0.02 0.00 0.00 0.00 0.00; 0.01 0.10 0.50 0.30 0.08 0.01 0.00 0.00 0.00; 0.00 0.02 0.15 0.51 0.26 0.06 0.01 0.00 0.00; 0.00 0.00 0.03 0.21 0.52 0.21 0.03 0.00 0.00 ; 0.00 0.00 0.01 0.06 0.26 0.51 0.15 0.02 0.00 ; 0.00 0.00 0.00 0.01 0.08 0.30 0.50 0.10 0.01 ; 0.00 0.00 0.00 0.00 0.02 0.11 0.35 0.47 0.05; 0.00 0.00 0.00 0.00 0.00 0.03 0.15 0.38 0.43]
convcrit = 0.001 # chosen convergence criterion
E_opt = Array{Float64}(gcc,gm,gz)
fill!(E_opt,10.0)
gridpoint_m = Array{Int64}(gcc,gm,gz)
fill!(gridpoint_m,fld(gkp,2))
v_dict=Dict(i => zeros(Float64,gm,gz) for i=1:gcc)
E_opt_dict=Dict(i => E_opt[i,:,:] for i=1:gcc)
gridpoint_m_dict=Dict(i => gridpoint_m[i,:,:] for i=1:gcc)
Для параллельной обработки я выполнил следующие две команды:
wp = CachingPool(workers())
addprocs(3)
pmap(wp,v_iter,values(v_dict),values(E_opt_dict),values(gridpoint_m_dict))
... который создал этот спектакль:
135.626417 seconds (3.29 G allocations: 57.152 GiB, 3.74% gc time)
Затем я попытался выполнить последовательную обработку:
for i=1:gcc
v_iter(v_dict[i],E_opt_dict[i],gridpoint_m_dict[i])
end
... и получил лучшую производительность.
128.263852 seconds (3.29 G allocations: 57.101 GiB, 4.53% gc time)
Это также дает мне примерно ту же производительность, что и запуск v_iter
на оригинальных трехмерных объектах:
v=zeros(Float64,gcc,gm,gz)
for i=1:gcc
v_iter(v[i,:,:],E_opt[i,:,:],gridpoint_m[i,:,:])
end
Я знаю, что параллельная обработка требует времени установки, но когда я увеличиваю значение gcc
, я все равно получаю примерно равное время обработки для последовательной и параллельной. Это кажется хорошим кандидатом для параллельной обработки, поскольку нет необходимости в обмене сообщениями между рабочими! Но я не могу заставить его работать эффективно.