Трансляция двумерного массива с многомерным массивом в Юлии - PullRequest
3 голосов
/ 14 июня 2019

У меня есть двумерная матрица, A, размера m x n, где n может быть очень большим числом (например, n> 10000), и многомерная матрица размера m x m x n. Итак, для каждого столбца i в A я хочу вычислить A[:,i]'*B[:,:,i]. Ниже приведены коды, которые я пробовал с помощью функции трансляции в Джулии. Тем не менее, производительность моего кода довольно низкая. Мне интересно, можно ли улучшить производительность моего кода. Итак, кто-то имеет представление о том, как я могу улучшить коды?

using LinearAlgebra;
m = 500;
n = 20000; # this could be a very large number.

vecA = rand(m,n);
matB = rand(m,m,n);


combinedAB = Array{Array{Float64,2},2}(undef,n,1);
for ii in eachindex(combinedAB)
  combinedAB[ii] = [vecA[:,ii] matB[:,:,ii]];
end

# this is the result.
res = broadcast(eAB -> dotProd(eAB), combinedAB);

function dotProd(matZ::Array{Float64,2})
   return sum(broadcast(dot,matZ[:,1],matZ[:,2:end]),dims=1);
end

1 Ответ

4 голосов
/ 14 июня 2019

Это достаточно быстро в вашем случае?

res = [a'*b for (a, b) in zip(eachcol(vecA), eachslice(matB, dims=3))]

У меня недостаточно оперативной памяти для проверки на соответствие вашим входным значениям, но, учитывая проведенные мною тесты для меньших данных, она должна выполняться через ~ 3 секунды.

Я также предполагаю, что вы действительно хотите присоединить к a (это то, что вы написали в своем вопросе; если вы работаете с реалами, не должно иметь значения, используете ли вы ' или transpose)

Ключевое различие между кодами (оно скрыто под капотом в моем решении, так как оно короче) состоит в том, что мое решение не выделяет промежуточные массивы, а использует представления.

...