мне нужно выполнить discretised свертку (комплексных) матриц, и определили следующую функцию в Julia:Эффективные поэлементно операции с матрицами в Julia
function convolve(M::Array{Complex{Float64},2}, K::Array{Float64,2}, p::Int)
(n,m) = size(M)
res = zeros(Complex{Float64},n)
for k=1:p
for l=1:n
res[l] += M[l,k]*K[l,end-p+k]
end
end
return res
end
я использую его следующим образом:
M=complex(rand(2000,2000))
K=rand(2000,2000)
@time convolve(M,K,2000,0)
Теперь это относительно быстро и удивительно, быстрее (примерно в 3 раза), чем в векторной версии, где я заменяю внутренний цикл res += M[:,k].*K[:,end-p+k]
. (Я думаю, что это связано с большим количеством распределения памяти для временных массивов, я могу с этим справиться).
Но vectorised MATLAB код работает примерно в 5 раз быстрее:
function res = convolve(M, K, p)
n = size(M,1);
res = zeros(n,1);
for k=1:p
res = res + M(:,k).*K(:,end-p+k);
end
end
Что я делаю не так, и как я могу получить Джулии выполнять такие поэлементно умножений так быстро, как MATLAB? Это проблема индексирования?
Примечание: Я проверил с @code_warntype
, что нет смешного бизнеса с типом нерешительности (нет Any
или Union
и т. Д.), Но проблема может быть более тонкой. Макрос @code_llvm
производит удивительно длинный вывод, но я не эксперт, поэтому мне трудно понять, что происходит.
Я думаю, что MATLAB автоматически будет выполнять многопоточность по элементарным операциям, хотя это еще экспериментально в Джулии. Протестируйте его на большой матрице и посмотрите, сколько ядер оно использует. –
Затем попробуйте Julia с 'Threads. @ Threads' перед циклом. –
Спасибо за ваш быстрый ответ. Я просто проверил это, и Matlab, похоже, не использует более одного процессора для квадратной матрицы из 2000 по 2000 элементов. Помещение потоков. @ Threads замедляет код julia большим фактором ... –