Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

optimize undefined variables better #6914

Closed
simonp0420 opened this issue May 22, 2014 · 7 comments
Closed

optimize undefined variables better #6914

simonp0420 opened this issue May 22, 2014 · 7 comments
Labels
performance Must go faster

Comments

@simonp0420
Copy link
Contributor

As shown below, fun1 takes 10x as long and allocates a large amount of memory, compared to fun2. fun2 differs only by initializing the local variable i.

julia> x = rand(10000000);

julia> function fun1(x::Vector{Float64})
           local i::Int
           for i = 1:length(x)
               if x[i] == 0.0
                   break
               end
           end
           return i-1
       end
fun1 (generic function with 1 method)

julia> function fun2(x::Vector{Float64})
           local i::Int = 0
           for i = 1:length(x)
               if x[i] == 0.0
                   break
               end
           end
           return i-1
       end
fun2 (generic function with 1 method)

julia> fun1(x); fun2(x); # warmup

julia> @time fun1(x)
elapsed time: 0.199774304 seconds (159998472 bytes allocated)
9999999

julia> @time fun2(x)
elapsed time: 0.020258781 seconds (64 bytes allocated)
9999999
@JeffBezanson JeffBezanson changed the title local for loop variable causes slowdown if not initialized prior to loop optimize undefined variables better May 22, 2014
@JeffBezanson
Copy link
Member

The real issue is that this code doesn't handle length(x)==0. Arguably we should give a compiler warning for that.

@StefanKarpinski
Copy link
Member

I think it would be good to issue a warning if a function can return an undefined value. I've also been thinking that it might be good to integrate bits of TypeCheck into Base so that it's easier to use.

@IainNZ
Copy link
Member

IainNZ commented May 22, 2014

Definitely a good idea Stefan, anything to save people from them selves.

You could maybe even go far as to say that its easier to make performance related mistakes in Julia for newbies (or at least, it seems like from reading the mailing lists that in terms of speed, bad julia < bad python/matlab < good python/matlab < good julia).

@StefanKarpinski
Copy link
Member

Another thought is that it could be an error to return an undefined value. That would allow this code to run at full speed and simply error out if x is empty.

@simonp0420
Copy link
Contributor Author

+1. A perhaps more reasonable example where this might be useful, but that currently is slow:

function fun1(x::Vector{Float64})
    @assert !isempty(x)
    local i::Int
    for i = 1:length(x)
        if x[i] == 0.0
            break
        end
    end
    return i-1
end

@JeffBezanson
Copy link
Member

@StefanKarpinski it doesn't need to specifically be an error to return an undefined value, because you get an error as soon as you access the undefined variable. The code already errors out if x is empty. The only reason it doesn't run at full speed is that we box i in order to make it "nullable".

JeffBezanson added a commit that referenced this issue Feb 14, 2015
thanks to @vtjnash for the test case.

It's hard to tell whether this is the real fix for the problem, but
it works, and having a type that's not a subtype of Any around was
just a huge pain. Things are simpler without it.

Inside the compiler, undefinedness is no longer part of a variable's
type. Instead there is a bit per variable telling whether it is ever
used when undefined. This has the disadvantage of being coarser, since
it doesn't give the undefinedness of each variable use. However it has
the advantage of giving better type info: if a variable is either a
Float64 or undefined, its type is just "Float64" and we can optimize
accordingly.

This combines well with the future optimization of storing
possibly-undefined variables unboxed (#6914).
For that we will add a run time 1-bit flag to track definedness, and
then LLVM can hopefully eliminate checks along paths where the
flag is known to be set, gaining back the previous granularity.
@JeffBezanson
Copy link
Member

Fixed by #18732.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
performance Must go faster
Projects
None yet
Development

No branches or pull requests

4 participants