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.
>>>>
>>>>
>>

Reply via email to