Julia 定义行为类似于堆叠阵列的类型
我有一个由多个数组组成的类型Julia 定义行为类似于堆叠阵列的类型,julia,Julia,我有一个由多个数组组成的类型 type VectorWrapper{T} x::Vector{T} y::Vector{T} end 我想要向量函数(比如说sumabs2,norm,scale!,copy!,fill!,axpy!,map!,reduce)对这种类型起作用,就好像它是一个叠加向量一样。例如,我想要以下内容: sumabs2(a) <-> sumabs2(a.x) + sumabs2(a.y) copy!(a1, a2) <-> copy!(
type VectorWrapper{T}
x::Vector{T}
y::Vector{T}
end
我想要向量函数(比如说sumabs2
,norm
,scale!
,copy!
,fill!
,axpy!
,map!
,reduce
)对这种类型起作用,就好像它是一个叠加向量一样。例如,我想要以下内容:
sumabs2(a) <-> sumabs2(a.x) + sumabs2(a.y)
copy!(a1, a2) <-> copy!(a1.x, a2.x) ; copy !(a1.y, a2.y)
但这并没有表现得那么好:
a = VectorWrapper(rand(10_000_000), rand(10_000_000))
@time sumabs2(a)
# 0.091090 seconds (7 allocations: 208 bytes)
@time sumabs2(a.x) + sumabs2(a.y)
# 0.010433 seconds (7 allocations: 208 bytes)
我猜sumabs2(a)
比sumabs2(a.x)+sumabs2(a.y)
慢,这是因为getindex
中添加了操作、绑定检查以及缺少SIMD矢量化
是否有一种将1的性能与2的简洁性结合起来的解决方案?如何定义堆叠阵列
v
作为主要组件,并将x
和y
作为其阵列视图。。。?例如:
type VecWrap{T} <: AbstractVector{T}
v::Vector{T}
x::Vector{T}
y::Vector{T}
function VecWrap{T}( x_in::Vector{T}, y_in::Vector{T} )
( nx, ny ) = ( length( x_in ), length( y_in ) )
v = Vector{T}( nx + ny )
v[ 1 : nx ] = x_in
v[ (nx+1) : (nx+ny) ] = y_in
x = pointer_to_array( pointer( v ), (nx,) )
y = pointer_to_array( pointer( v, nx+1 ), (ny,) )
return new( v, x, y )
end
end
Base.getindex( a::VecWrap, i::Int ) = a.v[ i ]
Base.setindex!( a::VecWrap, val, i::Int ) = ( a.v[ i ] = val )
Base.size( a::VecWrap ) = size( a.v )
Base.copy( a::VecWrap ) = VecWrap{Float64}( a.x, a.y )
Base.copy!( b::VecWrap, a::VecWrap ) = copy!( b.v, a.v )
function test()
n = 10_000_000
a = VecWrap{Float64}( rand( n ), rand( n ) )
for loop = 1:3
println( "loop = $loop" )
@time sumabs2( a )
@time sumabs2( a.x ) + sumabs2( a.y )
@time sumabs2( a.v )
end
end
加油!()etc似乎没有问题(尽管没有得到充分证实)。将x和y定义为子阵列似乎也能以几乎相同的效率(0.009-0.011秒)工作。
map
目前可能是一个性能陷阱,您是否尝试过在没有它的情况下编写size
方法
还有,你看到了吗?它似乎已经在做你想要的事情了
type VecWrap{T} <: AbstractVector{T}
v::Vector{T}
x::Vector{T}
y::Vector{T}
function VecWrap{T}( x_in::Vector{T}, y_in::Vector{T} )
( nx, ny ) = ( length( x_in ), length( y_in ) )
v = Vector{T}( nx + ny )
v[ 1 : nx ] = x_in
v[ (nx+1) : (nx+ny) ] = y_in
x = pointer_to_array( pointer( v ), (nx,) )
y = pointer_to_array( pointer( v, nx+1 ), (ny,) )
return new( v, x, y )
end
end
Base.getindex( a::VecWrap, i::Int ) = a.v[ i ]
Base.setindex!( a::VecWrap, val, i::Int ) = ( a.v[ i ] = val )
Base.size( a::VecWrap ) = size( a.v )
Base.copy( a::VecWrap ) = VecWrap{Float64}( a.x, a.y )
Base.copy!( b::VecWrap, a::VecWrap ) = copy!( b.v, a.v )
function test()
n = 10_000_000
a = VecWrap{Float64}( rand( n ), rand( n ) )
for loop = 1:3
println( "loop = $loop" )
@time sumabs2( a )
@time sumabs2( a.x ) + sumabs2( a.y )
@time sumabs2( a.v )
end
end
loop = 1
0.012153 seconds
0.009812 seconds
0.009667 seconds
loop = 2
0.011365 seconds
0.009657 seconds
0.009641 seconds
loop = 3
0.011350 seconds
0.009658 seconds
0.009665 seconds