On Sun, Mar 13, 2016 at 5:48 PM, Kristoffer Carlsson <kcarlsso...@gmail.com> wrote: > Erik, I believe the reason for all the moves is a recent regression: > https://github.com/JuliaLang/julia/issues/15274#issuecomment-196015327 > > James, the reason I need values in type parameters is because NTuples are > parameterized on a value and the immutable is wrapping an NTuple. The reason > I need to wrap an NTuple is because operations on NTuples of VecElements > (still in Arch's PR) generates packed instructions. The reason I need two > NTuples in the immutable is to put the "rest data", that is, the data that > does not fit in a SIMD register in a separate tuple and I do scalar > instructions on that tuple.
There is no need to split SIMD vectors like this. LLVM supports SIMD vectors of any length, and will then split it onto registers as necessary. In particular, LLVM should be able to use a partial vector register, which is more efficient than using several scalar registers. -erik > Here is the type definition and the getindex a few lines down: > https://github.com/KristofferC/SIMDVectors.jl/blob/master/src/SIMDVector.jl > > On Sunday, March 13, 2016 at 10:01:09 PM UTC+1, Jameson wrote: >> >> > 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`. >> >> Don't try this. As Yichao said, your code will return garbage memory and >> probably cause some other part of the system to crash (but of course, like >> all good memory bugs, only in production). >> >> This question sounds like a pre-optimization. Why do you need an object >> with values in the type parameters? That seems likely to cause the optimizer >> to waste quite a lot of memory. >> >> Also, FWIW, LLVM can already do this optimization with the code in the >> original post, but we turn it off in order to preserve the line numbers for >> the bounds-check (which increases code-size sometimes, but doesn't have much >> impact on speed). >> >> ``` >> julia> code_native(getindex, (Foo{1,1,Int}, Int)) >> .section __TEXT,__text,regular,pure_instructions >> Filename: none >> Source line: 3 >> pushq %rbp >> movq %rsp, %rbp >> cmpq $2, %rsi >> Source line: 3 >> movq -8(%rdi,%rsi,8), %rax >> popq %rbp >> ret >> ``` >> >> >> On Sunday, March 13, 2016 at 4:18:08 PM UTC-4, Yichao Yu wrote: >>> >>> On Sun, Mar 13, 2016 at 4:14 PM, Erik Schnetter <schn...@gmail.com> >>> wrote: >>> > I just tried accessing `a[i]` out of bounds, while promising >>> > `@inbounds` to Julia. Ideally, this would just work. Unfortunately, >>> >>> Doing this will at best return garbage and in general cause crashes. >>> >>> > 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 >>> > <kcarl...@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 <schn...@gmail.com> >>> > http://www.perimeterinstitute.ca/personal/eschnetter/ -- Erik Schnetter <schnet...@gmail.com> http://www.perimeterinstitute.ca/personal/eschnetter/