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

Implement efficent methods for any/all #32

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

goretkin
Copy link

Relates to issue #31

@johnnychen94
Copy link
Member

johnnychen94 commented Apr 21, 2020

Nice observation! I'm too busy to dig into the implementation of #31, if you do I'd be very happy to review it.

@timholy
Copy link
Member

timholy commented Apr 22, 2020

Would be nice to handle the predicate variants too.

@goretkin
Copy link
Author

Turns out the first behavior was broken anyway, because it did not properly handle missing. What's pushed now is slower, but should be correct. There should be a way to do short-circuit evaluation with trivalent logic: JuliaLang/julia#35563

One test will be broken, which is due to #33 as far as I can tell.

One test is failing, due to JuliaArrays#33
Handing `missing` at the cost of doing short-circuit evaluation, see
JuliaLang/julia#35563
@goretkin
Copy link
Author

I rebased to pull in the change in #34

@johnnychen94
Copy link
Member

I've tested locally that this patch fixes julia 1.0 and 0.7 tests

if v"0.7" <= VERSION < v"1.1"
    # ambiguity patch
    # https://github.com/JuliaLang/julia/pull/30904
    Base.all(::typeof(isinteger), ::PaddedView{<:Integer}) = true
end

@goretkin
Copy link
Author

Thanks for sorting that out! Feel free to push that fix, or let me know if I should.

@johnnychen94
Copy link
Member

Looks like I don't have push permission to your branch so I'll leave it to you.

@goretkin
Copy link
Author

Hm, yeah, I'm not sure how that works, since the branch is in my forked repo, but for what it's worth:

image

@johnnychen94
Copy link
Member

johnnychen94 commented Apr 23, 2020

Hmmm, no idea how to do that in my local machine. Just did it via github web.

Oh looks like vscode checkouts to another branch..

image

@goretkin
Copy link
Author

I don't think I know how to do it either. It would have to be related to this remote, not the goretkin one, so maybe it's some github hack.

Anyway, thanks for the push! Looks like it worked.

@johnnychen94
Copy link
Member

johnnychen94 commented Apr 23, 2020

Do you have plans to work on #31? Otherwise, we could merge this PR and probably tag a new release.

I'll merge it when you think it's ready.

Would be nice to handle the predicate variants too.

@timholy May I ask what "predicate variants" are? Sorry about this but I've never heard this word. Is that all(::PaddedViews)?

@goretkin
Copy link
Author

May I ask what "predicate variants" are?

I originally implemented e.g. all(::PaddedView), but now I implemented the more generic varaint which accepts a predicate f : all(f::Function, ::PaddedView). So the PR as it stands should address @timholy's comment.

I'd say this is a safe improvement over the current functionality, so it's good to merge. It's too bad it doesn't have the short-circuiting for efficiency, but that can be added later.

Copy link
Member

@johnnychen94 johnnychen94 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was about to merge and then I realized that this PR isn't ready.

🤔 Supporting dims efficiently isn't that trivial a task.

# The fallbacks work, but this is more efficient
# TODO use use short-circuit evaluation,
Base.any(f::Function, A::PaddedView) = f(A.fillvalue) | any(f, parent(A))
Base.all(f::Function, A::PaddedView) = f(A.fillvalue) & all(f, parent(A))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it doesn't support dims keyword

julia> pa = PaddedView(false, a, (1:2, 1:2));

julia> any(pa; dims=1)
ERROR: ArgumentError: No method is implemented for reducing index range of type typeof(i). Please implement
reduced_index for this index type or report this as an issue.

# The fallbacks work, but this is more efficient
# TODO use use short-circuit evaluation,
Base.any(f::Function, A::PaddedView) = f(A.fillvalue) | any(f, parent(A))
Base.all(f::Function, A::PaddedView) = f(A.fillvalue) & all(f, parent(A))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Base.all(A::PaddedView) = all(identity, A)

is still needed, otherwise it calls the fallback.

# The fallbacks work, but this is more efficient
# TODO use use short-circuit evaluation,
Base.any(f::Function, A::PaddedView) = f(A.fillvalue) | any(f, parent(A))
Base.all(f::Function, A::PaddedView) = f(A.fillvalue) & all(f, parent(A))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

julia> a = fill(true, 2, 2)
2×2 Array{Bool,2}:
 1  1
 1  1

julia> A = PaddedView(false, a, axes(a))
2×2 PaddedView(false, ::Array{Bool,2}, (Base.OneTo(2), Base.OneTo(2))) with eltype Bool:
 1  1
 1  1

julia> all(identity, A)
false

julia> all(identity, collect(A))
true

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@goretkin, I pointed this problem in JuliaLang/julia#35563 (comment).

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly, there is a problem with cropping.
I have a sense of foreboding about the combination of those and dims.:fearful:

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kimikage Yeah, I am not sure it is worthwhile to implement anything clever for dims. The required reasoning would be substantially more complex, and I can imagine it being slower for many cases where there isn't that much padding.

Not sure what problem with cropping you mean.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

julia> a = Bool[0 0; 1 1]
2×2 Array{Bool,2}:
 0  0
 1  1

julia> A = PaddedView(false, a, (1,3))
1×3 PaddedView(false, ::Array{Bool,2}, (Base.OneTo(1), Base.OneTo(3))) with eltype Bool:
 0  0  0

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the example! Yeah, that would also need to be handled for sure.

@goretkin
Copy link
Author

@johnnychen94 Thanks for catching #32 (comment)!

If we want to go forward with this idea, I can implement a [predicate] function that determines whether the fillvalue is activate (i.e. if there's any padding), and use that.

On second thought, a function that counts the number of fillvalue elements would be more generally useful if we wanted a similar optimization for other reductions.

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

Successfully merging this pull request may close these issues.

4 participants