Как вы уже догадались, ваша проблема в том, что массив, который вы вставляете в col
, всегда один и тот же: изменение массива за одну итерацию изменяет его везде.
Первый способ сделать, что вы хотите, чтобы copy
массив при вставке в col
:
function foo1(x::AbstractArray)
m, n = size(x)
col = Array{store}(undef, m, n)
A = zeros(m, n)
for i in eachindex(col)
A[i] = 1.0
col[i] = store(x[i], copy(A))
A[i] = 0
end
return col
end
Другим способом, как вы предлагаете, было бы создание нового массива A
на каждой итерации:
function foo2(x::AbstractArray)
m, n = size(x)
col = Array{store}(undef, m, n)
for i in eachindex(col)
A = zeros(m, n)
A[i] = 1.0
col[i] = store(x[i], A)
end
return col
end
Похоже, второй способ более эффективен:
julia> using BenchmarkTools
julia> x = rand(2,2)
2×2 Array{Float64,2}:
0.899445 0.459424
0.287892 0.669846
julia> @btime foo1($x)
241.078 ns (10 allocations: 800 bytes)
2×2 Array{store,2}:
store(0.899445, [1.0 0.0; 0.0 0.0]) store(0.459424, [0.0 1.0; 0.0 0.0])
store(0.287892, [0.0 0.0; 1.0 0.0]) store(0.669846, [0.0 0.0; 0.0 1.0])
julia> @btime foo2($x)
198.404 ns (9 allocations: 688 bytes)
2×2 Array{store,2}:
store(0.899445, [1.0 0.0; 0.0 0.0]) store(0.459424, [0.0 1.0; 0.0 0.0])
store(0.287892, [0.0 0.0; 1.0 0.0]) store(0.669846, [0.0 0.0; 0.0 1.0])
Как было сказано в другом ответе, было бы более эффективно хранить A
как SparseArray
, особенно если он имеет большой размер:
using SparseArrays
function foo3(x::AbstractArray)
m, n = size(x)
col = Array{store}(undef, m, n)
for i in eachindex(col)
A = spzeros(m, n)
A[i] = 1.0
col[i] = store(x[i], A)
end
return col
end
Эта стратегия не платит для таких небольших размеров, но должен быть наиболее эффективным, если ваша реальная проблема больше:
julia> @btime foo3($x)
829.851 ns (33 allocations: 1.92 KiB)
2×2 Array{store,2}:
store(0.899445, [1, 1] = 1.0) store(0.459424, [1, 2] = 1.0)
store(0.287892, [2, 1] = 1.0) store(0.669846, [2, 2] = 1.0)