> Jamie, that diary of yours is great reading, btw.

Thanks :)

> I'm pretty intrigued by the mystery of why the Julia version is 2x slower.

Me too. I'm trying to systematically remove anything that might cause
a difference, hence these fixed-length arrays. I want to be able to
rule out the extra logic inside the Julia arrays as a cause.

On 8 January 2016 at 20:12, Stefan Karpinski <ste...@karpinski.org> wrote:
> Jamie, that diary of yours is great reading, btw. I'm pretty intrigued by
> the mystery of why the Julia version is 2x slower. I would be very
> interested in getting to the bottom of that.
>
> On Fri, Jan 8, 2016 at 2:37 PM, Stefan Karpinski <ste...@karpinski.org>
> wrote:
>>
>> Setting the fix-size mutable array thing aside, one thing that's glaringly
>> wrong about these examples is that even if parametric types were covariant,
>> this wouldn't make sense because 4 <: Any is never going to be true because
>> 4 is not a type, it's a value:
>>
>> julia> 4 <: Any
>> ERROR: TypeError: subtype: expected Type{T}, got Int64
>>  in eval at ./boot.jl:265
>>
>>
>> The fact that you can write NTuple{Any,Int} at all seems to be a bug:
>>
>> julia> NTuple{Any,Int}
>> ERROR: TypeError: NTuple: in parameter 1, expected Int64, got Type{Any}
>>  in eval at ./boot.jl:265
>>
>> julia> NTuple{ANY,Int}
>> NTuple{ANY,Int64}
>>
>>
>> I'm not sure what's going on with that, but I've filed an issue: #14607.
>>
>> On Fri, Jan 8, 2016 at 2:00 PM, 'Jamie Brandon' via julia-users
>> <julia-users@googlegroups.com> wrote:
>>>
>>> > If you don't want to specialize on the length of the array why include
>>> > it in the type at all?
>>>
>>> I built a HAMT using normal Julia arrays and found that the extra size
>>> and extra pointer hop made them around 2x larger and 4x slower than
>>> the totally naive Rust equivalent. (If you want excruciating amounts
>>> of detail, see
>>> https://github.com/jamii/imp/blob/master/diary.md#baseline).
>>> I'm now trying to implement fixed-length mutable arrays, much like
>>> https://github.com/JuliaLang/julia/issues/12447
>>>
>>> type NArray{N,T}
>>>   contents::NTuple{N,T}
>>> end
>>>
>>> If I take the size out it will just box the ntuple.
>>>
>>> I can work around the constructor. I'm more interested in
>>> understanding how ANY affects variance so I know in what cases I can
>>> use it:
>>>
>>> julia> NTuple{4, Int64} <: NTuple{ANY, Int64}
>>> true
>>> julia> Hamt.NArray{4,Int64} <: Hamt.NArray{ANY,Int64}
>>> true
>>>
>>> julia> Type{NTuple{4,Int64}} <: Type{NTuple{ANY,Int64}}
>>> true
>>> julia> Type{Hamt.NArray{4,Int64}} <: Type{Hamt.NArray{ANY,Int64}}
>>> false
>>>
>>> julia> Tuple{NTuple{4,Int64}} <: Tuple{NTuple{ANY,Int64}}
>>> true
>>> julia> Tuple{Hamt.NArray{4,Int64}} <: Tuple{Hamt.NArray{ANY,Int64}}
>>> true
>>>
>>> julia> Vector{NTuple{4,Int64}} <: Vector{NTuple{ANY,Int64}}
>>> true
>>> julia> Vector{Hamt.NArray{4,Int64}} <: Vector{Hamt.NArray{ANY,Int64}}
>>> false
>>>
>>> >> julia> arr = Hamt.NArray{10, Int64}()
>>> >> ERROR: MethodError: `convert` has no method matching
>>> >> convert(::Type{Hamt.NArray{10,Int64}})
>>> >> This may have arisen from a call to the constructor
>>> >> Hamt.NArray{10,Int64}(...),
>>> >> since type constructors fall back to convert methods.
>>> >> Closest candidates are:
>>> >>   convert{T}(::Type{T}, ::T)
>>> >>   Hamt.NArray{N,T}(, ::Any)
>>> >>   call{T}(::Type{T}, ::Any)
>>> >>  in call at essentials.jl:57
>>> >>
>>> >> julia> arr = Hamt.Array{Int64}()
>>> >> ERROR: argument is an abstract type; size is indeterminate
>>> >>  in call at /home/jamie/code/imp/src/Hamt.jl:23
>>> >>
>>> >> I have this doing exactly what I want with the bare types eg:
>>> >>
>>> >> Base.getindex{T}(narray::NArray{ANY,T}, ix::Integer)
>>> >>
>>> >> I'm just struggling getting the same behaviour from the constructor
>>> >> because of the way Type varies.
>>> >
>>> >
>>> > So one issue here is that using ANY like this doesn't mean what you
>>> > want it
>>> > to – it means that the first parameter of  NArray is the literal value
>>> > ANY.
>>> > So when you write call{T}(t::Type{Array{T}}) it literally means
>>> > call{T}(t::Type{NArray{ANY,T}}) – which is not what you want. Instead,
>>> > you'd
>>> > want a typealias like this:
>>> >
>>> > typealias TArray{T,n} NArray{n,T}
>>> >
>>> > call{T}(t::Type{TArray{T}}) = ...
>>> >
>>> >
>>> > But I'm getting a little confused about what you're trying to
>>> > accomplish
>>> > with that type parameter for the number of elements in the first place.
>>>
>>> On 8 January 2016 at 18:23, Stefan Karpinski <ste...@karpinski.org>
>>> wrote:
>>> > On Fri, Jan 8, 2016 at 1:12 PM, 'Jamie Brandon' via julia-users
>>> > <julia-users@googlegroups.com> wrote:
>>> >>
>>> >> > Yes, it's like any other parametric type that way.
>>> >>
>>> >> Are tuples treated specially? eg:
>>> >
>>> >
>>> > Yes, tuples types are covariant while everything else is invariant.
>>> >
>>> >> > ANY is a hack to let you hint to the compiler that it should not
>>> >> > specialize a method on an argument.
>>> >>
>>> >> That's exactly what I'm trying to achieve. I really don't want my
>>> >> array functions to specialize on the length of the array :)
>>> >
>>> >
>>> > If you don't want to specialize on the length of the array why include
>>> > it in
>>> > the type at all?
>>> >
>>> >>
>>> >> > Currently you have to use a typealias...
>>> >>
>>> >> I'm not having any luck with this.
>>> >>
>>> >> typealias Array{T} NArray{ANY,T}
>>> >>
>>> >> call{T}(t::Type{Array{T}}) = begin
>>> >>   tp = pointer_from_objref(t)
>>> >>   size = sizeof(t)
>>> >>   ...
>>> >> end
>>> >>
>>> >> julia> arr = Hamt.NArray{10, Int64}()
>>> >> ERROR: MethodError: `convert` has no method matching
>>> >> convert(::Type{Hamt.NArray{10,Int64}})
>>> >> This may have arisen from a call to the constructor
>>> >> Hamt.NArray{10,Int64}(...),
>>> >> since type constructors fall back to convert methods.
>>> >> Closest candidates are:
>>> >>   convert{T}(::Type{T}, ::T)
>>> >>   Hamt.NArray{N,T}(, ::Any)
>>> >>   call{T}(::Type{T}, ::Any)
>>> >>  in call at essentials.jl:57
>>> >>
>>> >> julia> arr = Hamt.Array{Int64}()
>>> >> ERROR: argument is an abstract type; size is indeterminate
>>> >>  in call at /home/jamie/code/imp/src/Hamt.jl:23
>>> >>
>>> >> I have this doing exactly what I want with the bare types eg:
>>> >>
>>> >> Base.getindex{T}(narray::NArray{ANY,T}, ix::Integer)
>>> >>
>>> >> I'm just struggling getting the same behaviour from the constructor
>>> >> because of the way Type varies.
>>> >
>>> >
>>> > So one issue here is that using ANY like this doesn't mean what you
>>> > want it
>>> > to – it means that the first parameter of  NArray is the literal value
>>> > ANY.
>>> > So when you write call{T}(t::Type{Array{T}}) it literally means
>>> > call{T}(t::Type{NArray{ANY,T}}) – which is not what you want. Instead,
>>> > you'd
>>> > want a typealias like this:
>>> >
>>> > typealias TArray{T,n} NArray{n,T}
>>> >
>>> > call{T}(t::Type{TArray{T}}) = ...
>>> >
>>> >
>>> > But I'm getting a little confused about what you're trying to
>>> > accomplish
>>> > with that type parameter for the number of elements in the first place.
>>
>>
>

Reply via email to