I just tried accessing `a[i]` out of bounds, while promising `@inbounds` to Julia. Ideally, this would just work. Unfortunately, Julia currently copies the argument `v` via a long sequence of move instructions, making this (a) work but (b) inefficient.
-erik On Sun, Mar 13, 2016 at 2:48 PM, Kristoffer Carlsson <kcarlsso...@gmail.com> wrote: > I would have hoped that this would generate the same code: > > immutable Foo{M, N, T} > a::NTuple{M, T} > b::NTuple{N, T} > end > > > immutable Foo2{N, T} > a::NTuple{N, T} > end > > > @inline function gimmie{M, N, T}(v::Foo{M, N, T}, i) > p = convert(Ptr{T}, pointer_from_objref(v)) > return unsafe_load(p, i) > end > > @inline function gimmie{N, T}(v::Foo2{N, T}, i) > @inbounds val = v.a[i] > return val > end > > @inline function gimmie{N, T}(v::NTuple{N, T}, i) > @inbounds val = v[i] > return val > end > > a = Foo( (1.0,2.0), (3.0,4.0,5.0) ) > b = Foo2( (1.0,2.0,3.0,4.0,5.0) ) > c = ((1.0,2.0,3.0,4.0,5.0)) > > @code_native gimmie(a, 1) > @code_native gimmie(b, 1) > @code_native gimmie(c, 1) > > But the code for Foo is more complicated. It includes calling for example > jl_gc_allocobj. > > Do you know if there is a way to get a zero overhead access as compared to > the one tuple version? > > On Sunday, March 13, 2016 at 3:42:18 PM UTC+1, Erik Schnetter wrote: >> >> Do you actually need a type declaration like this, or could you write >> the equivalent of >> ```Julia >> immutable Foo2{M, N, T} >> ab::NTuple{M+N, T} >> end >> ``` >> and the introduce functions `geta` and getb` for `Foo`? This would be >> a completely type-safe solution. >> >> On the other hand, if you are sure that the memory layout is as you >> expect, you can always go the C way: Get a pointer to `Foo`, >> unsafe-cast that pointer to `Foo2`, and access the elements via >> `Foo2`. >> >> -erik >> >> >> On Sun, Mar 13, 2016 at 7:57 AM, Kristoffer Carlsson >> <kcarl...@gmail.com> wrote: >> > Hello everyone. >> > >> > Assume I have an immutable like: >> > >> > immutable Foo{M, N, T} >> > a::NTuple{M, T} >> > b::NTuple{N, T} >> > end >> > >> > and I want to make an efficient getindex into the tuple. >> > >> > Something that would probably be inefficient due to branching would be: >> > >> > function Base.getindex{M, N}(f::Foo({M,N}), i) >> > if i <= M >> > return f.a[i] >> > else >> > return f.b[i - N] >> > end >> > end >> > >> > Is there anyway I can just grab the value at the address at an offset i >> > - 1 >> > further forward of the address of f.a[1]. In my head this would be more >> > efficient since it would be a very simple offset calculation. You can >> > assume >> > that T is a nice bits type like a Float32. >> > >> > Thanks! >> > >> > // Kristoffer >> > >> > >> > >> > >> >> >> >> -- >> Erik Schnetter <schn...@gmail.com> >> http://www.perimeterinstitute.ca/personal/eschnetter/ -- Erik Schnetter <schnet...@gmail.com> http://www.perimeterinstitute.ca/personal/eschnetter/