If you're indexing into an external array in Julia without any additional annotation, there's quite a bit more going on than in C++ – C++ does array accesses without any regards for safety. First, make sure that the array that you're indexing into is a constant – if it isn't Julia has no chance of generating decent code since it has no idea what the type of the array or its elements are, or where it is in memory. Next, you'll want to turn of bounds checking of the array with @inbounds. Of course, you'll want to be *very* sure that you're not going out of bounds when you do this or you'll get segfaults just like you would in C/C++. For example, if I do this:
const f = [1,2,3] sf(i) = @inbounds return f[i>>16+1] + f[i&65535+1] lt(i,j) = sf(i) < sf(j) Then the native code for lt(::Int,::Int) is julia> @code_native lt(1,2) .section __TEXT,__text,regular,pure_instructions Filename: none Source line: 1 push RBP mov RBP, RSP Source line: 1 movzx ECX, SI movabs RAX, 140305558344800 mov RAX, QWORD PTR [RAX] mov RAX, QWORD PTR [RAX + 8] mov RCX, QWORD PTR [RAX + 8*RCX] sar RSI, 16 add RCX, QWORD PTR [RAX + 8*RSI] movzx EDX, DI mov RDX, QWORD PTR [RAX + 8*RDX] sar RDI, 16 add RDX, QWORD PTR [RAX + 8*RDI] cmp RDX, RCX setl AL pop RBP ret That's quite respectable. If I leave out the const or the @inbounds, then it's not nearly so neat and tidy. On Fri, Jul 4, 2014 at 9:51 AM, gentlebeldin <[email protected]> wrote: > Unfortunately, my happiness was a bit premature. With a simple function > like f(x)=x or f(x)=sin(x), it works, that's inlined, as it seems. If the > function is more complicated, it isn't, and we're back at many seconds, and > memory allocation of gigabytes for sorting an array of 1000000 elements. :-( > In C++11, that works: > vector<int> arr(S); > for(int i = 0, k = 0; k <= M; k++) > for(int l = k; l <= M; l++, i++) > arr[i] = (k << 16) + l; > > sort (arr.begin(), arr.end(), [](int i, int j) > { > return (sf(i) < sf(j)); > }); > > Here, sf is a more complex function, sf(i)=f[i>>16+1]+f[i&65535+1], where > the array f is precomputed > The syntax of a lambda expression (since C++11) is rather strange, but the > implementation seems to be efficient, it's actually much faster than > defining the lt function outside. > As it seems, I won't be able port that to Julia. > > Am Freitag, 4. Juli 2014 15:22:08 UTC+2 schrieb Stefan Karpinski: >> >> Yes, exactly. Sorry I was not especially helpful yesterday – was on my >> phone. But you seem to have figured it out. Sorry also that this is not the >> most elegant interface. Obviously the longer term is to make passing >> functions as arguments more efficient. >> >> >> On Fri, Jul 4, 2014 at 5:36 AM, gentlebeldin <[email protected]> >> wrote: >> >>> I guess you mean something like this: >>> >>> julia> using Base.Order >>> >>> julia> import Base.lt >>> >>> julia> type MyNewOrdering<:Ordering >>> end >>> >>> julia> f(x::Float64)=x >>> f (generic function with 1 method) >>> >>> >>> julia> lt(o::MyNewOrdering,x::Float64,y::Float64)=f(x)<f(y) >>> lt (generic function with 9 methods) >>> >>> >>> julia> a=rand(1000000) >>> 1000000-element Array{Float64,1}: >>> ... >>> >>> julia> @time sort(a,order=MyNewOrdering()) >>> elapsed time: 0.119845282 seconds (8000496 bytes allocated) >>> 1000000-element Array{Float64,1}: >>> ... >>> >>> >>> Yes, that's better, both time and memory allocation. Thank you very >>> much! :-) >>> >>> Am Donnerstag, 3. Juli 2014 21:14:05 UTC+2 schrieb Stefan Karpinski: >>> >>>> You can also define your own subtype of Order. See base/order.jl. >>>> >>>> >>
