N = 10^8
n = 3
# A.^2 を B にコピーする函数のつもり
#
function test!(B, A)
B .= A.^2
end
test! (generic function with 1 method)
A = reshape(collect(1:2N), N, 2)
A[1:n,:]
3×2 Array{Int64,2}: 1 100000001 2 100000002 3 100000003
# A[:,2] に A[:,1].^2 がコピーされない上に遅い.
A = reshape(collect(1:2N), N, 2)
test!(A[:,2], A[:,1])
A = reshape(collect(1:2N), N, 2)
@time test!(A[:,2], A[:,1])
A[1:n,:]
0.984741 seconds (89 allocations: 1.490 GiB, 23.17% gc time)
3×2 Array{Int64,2}: 1 100000001 2 100000002 3 100000003
# @view(A[:,2]) を函数に渡すと A[:,1].^2 がコピーされる.
A = reshape(collect(1:2N), N, 2)
test!(@view(A[:,2]), A[:,1])
A = reshape(collect(1:2N), N, 2)
@time test!(@view(A[:,2]), A[:,1])
A[1:n,:]
0.572699 seconds (33 allocations: 762.940 MiB, 20.10% gc time)
3×2 Array{Int64,2}: 1 1 2 4 3 9
@macroexpand test!(@view(A[:,2]), A[:,1])
:(test!(true && (view)(A, :, 2), A[:, 1]))
# さらに @view(A[:,1]) とすると速くなり, メモリ効率が大幅に改善される.
A = reshape(collect(1:2N), N, 2)
test!(@view(A[:,2]), @view(A[:,1]))
A = reshape(collect(1:2N), N, 2)
@time test!(@view(A[:,2]), @view(A[:,1]))
A[1:n,:]
0.146387 seconds (56 allocations: 1.188 KiB)
3×2 Array{Int64,2}: 1 1 2 4 3 9
@macroexpand test!(@view(A[:,2]), @view(A[:,1]))
:(test!(true && (view)(A, :, 2), true && (view)(A, :, 1)))
@which view(A, :, 2)
# マクロではない view を使っても同じことをできる.
A = reshape(collect(1:2N), N, 2)
test!(view(A,:,2), view(A,:,1))
A = reshape(collect(1:2N), N, 2)
@time test!(view(A,:,2), view(A,:,1))
A[1:n,:]
0.146301 seconds (56 allocations: 1.188 KiB)
3×2 Array{Int64,2}: 1 1 2 4 3 9
# @views を使えばさらにシンプルに書ける.
A = reshape(collect(1:2N), N, 2)
@views test!(A[:,2], A[:,1])
A = reshape(collect(1:2N), N, 2)
@time @views test!(A[:,2], A[:,1])
A[1:n,:]
0.142722 seconds (60 allocations: 1.250 KiB)
3×2 Array{Int64,2}: 1 1 2 4 3 9
@macroexpand @views test!(A[:,2], A[:,1])
:(test!((Base.maybeview)(A, :, 2), (Base.maybeview)(A, :, 1)))
@which Base.maybeview(A, :, 2)