Юлия хранит массивы в главном порядке столбцов . Это означает, что срезы, такие как arr[i, : ,:]
, работают намного хуже, чем arr[:,:,i]
(который непрерывен в памяти). Поэтому способ получить некоторую скорость - индексировать массивы, используя (h,w,t)
, а не (t, w, h)
.
Вторая проблема заключается в том, что при взятии фрагментов, подобных arr[i,:,:]
, копируются данные. Кажется, что это имеет незначительное влияние, но было бы неплохо привыкнуть к , используя представления массива вместо срезов , когда это возможно. Представление - это небольшой объект-обертка, который ведет себя так же, как и фрагмент большего массива, но не содержит копию данных: он напрямую обращается к данным родительского массива (см. Пример ниже, чтобы лучше понять, что представление есть).
Обратите внимание, что обе эти проблемы упоминаются в советах по производительности Julia ; может быть полезно прочитать оставшиеся советы на этой странице.
Соединив это, ваш пример можно переписать так:
function applyResize2!(arr3D_hd::Array, arr3D_ld::Array, h::Int, w::Int, t)
@inbounds for i = 1:1:t
A = interpolate(@view(arr3D_ld[:, :, i]), BSpline(Linear()))
arr3D_hd[:, :, i] .= A(1:2/(h-1)/2:2, 1:2/(w-1)/2:2)
end
end
, который используется с массивами, хранящимися немного по-другому от вашего случая:
# Note the order of indices
julia> arr3D_ld = reshape(collect(1:t*h*w), (h, w, t));
julia> arr3D_hd = Array{Float32}(undef, h_target, w_target, t);
# Don't forget to escape arguments with a $ when using btime
# (not really an issue here, but could have been one)
julia> @btime applyResize2!($arr3D_hd, $arr3D_ld, h_target, w_target, t)
506.449 ms (6024 allocations: 840.11 MiB)
Это примерно в 3,4 раза быстрее, чем ваш исходный код, что соответствует тестам на моей машине:
julia> arr3D_ld = reshape(collect(1:t*h*w), (t, h, w));
julia> arr3D_hd = Array{Float32}(undef, t, h_target, w_target);
julia> @btime applyResize!($arr3D_hd, $arr3D_ld, t, h_target, w_target)
1.733 s (50200 allocations: 857.30 MiB)
NB: Ваш исходный код использует синтаксис, такой как A[x, y]
, для получения интерполированных значений. Похоже, это не рекомендуется в пользу A(x, y)
. Возможно, у меня не такая же версия Interpolations
, как у вас, хотя ...
Пример, иллюстрирующий поведение представлений
julia> a = rand(3,3)
3×3 Array{Float64,2}:
0.042097 0.767261 0.0433798
0.791878 0.764044 0.605218
0.332268 0.197196 0.722173
julia> v = @view(a[:,2]) # creates a view instead of a slice
3-element view(::Array{Float64,2}, :, 2) with eltype Float64:
0.7672610491393876
0.7640443797187411
0.19719581867637093
julia> v[3] = 42 # equivalent to a[3,2] = 42
42