On Tue, Apr 12, 2016 at 9:43 AM, DNF <[email protected]> wrote:
> Ah! [Foreheadslapping] For some reason I thought it didn't matter in this
> case, but of course it does.
>
> So, is this less of a problem with NTuple as array then, than with Tuple,
> because the length is known?
NTuple is just a constructor for tuple so there's no difference.
The point is when you want to use it as an array, you generally don't
care about the size of the array at compile time, only at runtime.
However, using a tuple in many case force the compiler to know about
the size in order to generate the right code.
This is in general true for putting more info into the type. You can
get more specialized code (which may or may not have any runtime
performance boost), but will almost certainly have compile time cost.
Bad example of putting more info into the type includes using
`Val{true}`/`Val{false}` as boolean flags or use tuple as array (at
least naively, there might be ways to (unsafely?) workaround
this....).
>
>
> On Tuesday, April 12, 2016 at 3:06:09 PM UTC+2, Yichao Yu wrote:
>>
>> On Tue, Apr 12, 2016 at 5:43 AM, DNF <[email protected]> wrote:
>> > Wow! That is a huge difference.
>> >
>> > I suspected that my benchmark was flawed, but I don't understand in what
>> > way, since is doesn't seem like anything is being inappropriately
>> > optimized
>> > away. Quite the contrary, my benchmark is running slowly with lots of
>> > allocations.
>> >
>> > The question remains, though, when is Vector better/faster in cases when
>> > both vectors and tuples are possible to use? Are arrays always this slow
>> > compared to tuples?
>> >
>> > As for what's holding me back from using FixedSizeArray: nothing but
>> > pure
>> > ignorance!
>> >
>> >
>> > On Tuesday, April 12, 2016 at 11:06:25 AM UTC+2, Simon Danisch wrote:
>> >>
>> >> Your benchmark is flawed.
>> >> Try something like the Benchmarks package, or use this:
>> >>
>> >> using FixedSizeArrays
>> >> Base.(:+){T}(p1::NTuple{2,T}, p2::NTuple{2,T}) = (p1[1]+p2[1],
>> >> p1[2]+p2[2])
>> >> function test(a, b, N)
>> >> ct = a+b
>> >> for _ in 1:N ct = ct+a+b end # use intermediate result so that
>> >> llvm
>> >> doesn't just remove the loop
>> >> ct # return value so it doesn't get optimized away
>> >> end
>> >> a, b = randn(2), randn(2)
>> >> at, bt = (randn(2)...), (randn(2)...)
>> >> p1, p2 = Point2D(randn(2)...), Point2D(randn(2)...)
>>
>> ^^^ These are not type stable even in a function due to the splatting.
>> The compiler has to know the size of the array to know the type of the
>> tuple. This is the main issue with using tuple as array, you easily
>> get dynamic dispatch or a crazy amount of codegen without realizing
>> it.
>>
>> >>
>> >> #warm up
>> >> test(a,b,10^7)
>> >> test(at,bt,10^7)
>> >> test(p1,p1,10^7)
>> >>
>> >>
>> >> @time test(a,b,10^7) # 1.175718 seconds (40.00 M allocations: 1.788 GB,
>> >> 9.77% gc time)
>> >> @time test(at,bt,10^7) #0.017781 seconds (6 allocations: 208 bytes)
>> >> @time test(p1,p1,10^7) #0.017783 seconds (6 allocations: 208 bytes)
>> >>
>> >>
>> >> As you can see, tuples and types are pretty much the same, while Vector
>> >> is
>> >> far behind.
>> >> In this benchmark, it's mainly because the Vector is heap allocated.
>> >> Tuples are preferable to types, since they have the same performance,
>> >> but
>> >> you can implement n-dimensional point types.
>> >> If you already found FixedSizeArrays, what's holding you back of using
>> >> it?
>> >> It already has the Point{N, T} type and GeometryTypes.jl has even more
>> >> ;)
>> >>
>> >> Best,
>> >> Simon
>> >> Am Montag, 11. April 2016 22:00:59 UTC+2 schrieb Anonymous:
>> >>>
>> >>> If I have a vector of data which I don't intend to ever change, should
>> >>> I
>> >>> represent it as a tuple rather than a 1d array? Is there any benefit
>> >>> above
>> >>> and beyond protecting against mutability? Is it more efficient?