给定Julia中的某个对角矩阵,如A = Diagonal(rand(3,3))
,是否有办法创建一个一维数组,其元素是这个对角矩阵A
的对角项?
有一个diag(A, k::Integer=0)
,它返回矩阵a的第k个对角线,作为一个向量。
julia> A = Diagonal(rand(3,3))
3×3 Diagonal{Float64, Vector{Float64}}:
0.213159 ⋅ ⋅
⋅ 0.034186 ⋅
⋅ ⋅ 0.539693
julia> diag(A)
3-element Vector{Float64}:
0.21315894297089488
0.03418604147090787
0.5396925608269262
从本质上讲,不分配/复制任何内存并直接从存储的矩阵中访问矩阵的对角线是有意义的。理想情况下,这个对角线的抽象向量接口隐藏了必要的内存位置计算。
这可以使用Strided
包实现。要安装包,通常输入:
using Pkg
Pkg.add("Strided")
。
问题中的例子可以这样解决:
julia> using Strided
julia> A = rand(3,3)
3×3 Matrix{Float64}:
0.627885 0.996657 0.5304
0.290007 0.19639 0.0311003
0.0931983 0.912228 0.227603
julia> D = Strided.UnsafeStridedView(pointer(A), (3,), (4,), 0)
3-element Strided.UnsafeStridedView{Float64, 1, Float64, typeof(identity)}:
0.6278853842183714
0.1963898010179035
0.22760324615233707
这个例子有3x3矩阵大小硬编码。3
和4
在StridedView定义应该改变为矩阵大小(和size+1)。重要的是,原始矩阵是一个密集的正常布局矩阵,而不是稀疏的或任何其他矩阵在Julia中的实现。
使用这种方法的好处是大约10倍的速度。基准测试结果如下:
julia> @btime Strided.UnsafeStridedView(pointer($A), (3,), (4,), 0)
1.885 ns (0 allocations: 0 bytes)