How to implement fast range reads for my custome-defined array?

I need to implement my own array type underlying which is still a Vector, but reading/writing to it is much much slower than reading/writing the vanilla Julia array. I can reproduce the problem in this simple program below. Could someone see what I did wrong?


type MyArray{T, N} <: AbstractArray{T, N}
    values::Vector{T}
    dims::Tuple
    MyArray(dims::NTuple{N, Int64}) = length(dims) > 0 ?
        new(Vector{T}(reduce(*, [dims...])), dims) :
        new(Vector{T}(), dims)
end

function Base.linearindexing(::MyArray)
    return Base.LinearFast()
end

function Base.size(array::MyArray)
    return array.dims
end

function Base.getindex(array::MyArray, i::Int)
    return array.values[i]
end

function Base.setindex!(array::MyArray, v, i::Int)
    array.values[i] = v
end

function Base.similar{T, N}(array::MyArray{T, N}, ::Type{T}, dims::NTuple{N, Int64})
    return MyArray{T, N}(dims)
end

c = MyArray{Float64, 2}((100, 3000))
@time for i = 1:3000
    d = c[:, i]
end

a = rand((100, 3000))
@time for i = 1:3000
    b = a[:, i]
end

According to the output of @time, it seems my implementation causes a lot more memory allocation than Julia’s. How may I fix it?

4.525247 seconds (10.35 M allocations: 228.042 MB, 3.78% gc time)
0.025936 seconds (28.96 k allocations: 3.634 MB)

Your dims::Tuple field is not concretely typed. Perhaps it should be ::NTuple{N, Int}?.

Also, it is unikely that you want to have that type be mutable so change to immutable (or just struct in the new syntax). Note, making the type non mutable does not mean you cannot mutate the values in the values field.

4 Likes

Thanks! This solved my problem!