-
Notifications
You must be signed in to change notification settings - Fork 37
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
WIP: collect without inference #135
Merged
Merged
Changes from 1 commit
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
cf31fa0
collect without inference
ef30634
use generated function to optimize type checking step
a74cbe7
only change relevant columns
0814597
remove incorrect typeassert
59347bb
fix test
6c05925
refactor and add scalar case
89cc30e
unknown length
dac0578
rename to collect_columns
1f51b23
change to promote_type
ca280ef
docs
d196912
typo
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
collectcolumns(itr) = collectcolumns(itr, Base.iteratorsize(itr)) | ||
|
||
function collectcolumns(itr, ::Union{Base.HasShape, Base.HasLength}) | ||
st = start(itr) | ||
el, st = next(itr, st) | ||
dest = similar(arrayof(typeof(el)), length(itr)) | ||
dest[1] = el | ||
collect_to_columns!(dest, itr, 2, st) | ||
end | ||
|
||
function collect_to_columns!(dest::Columns{T, U}, itr, offs, st) where {T, U} | ||
# collect to dest array, checking the type of each result. if a result does not | ||
# match, widen the result type and re-dispatch. | ||
i = offs | ||
while !done(itr, st) | ||
el, st = next(itr, st) | ||
S = typeof(el) | ||
if all((s <: t) for (s, t) in zip(S.parameters, T.parameters)) | ||
@inbounds dest[i] = el::T | ||
i += 1 | ||
else | ||
Rparams = map(typejoin, T.parameters, S.parameters) | ||
R = get_tuple_type_from_params(el, Rparams) | ||
new = similar(arrayof(R), length(itr)) | ||
@inbounds for l in 1:i-1; new[l] = dest[l]; end | ||
@inbounds new[i] = el | ||
return collect_to_columns!(new, itr, i+1, st) | ||
end | ||
end | ||
return dest | ||
end | ||
|
||
get_tuple_type_from_params(el::Tuple, params) = Tuple{params...} | ||
get_tuple_type_from_params(el::NamedTuple, params) = eval(:(NamedTuples.@NT($(keys(el)...)))){params...} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
@testset "collectnamedtuples" begin | ||
v = [@NT(a = 1, b = 2), @NT(a = 1, b = 3)] | ||
@test collectcolumns(v) == Columns(@NT(a = Int[1, 1], b = Int[2, 3])) | ||
|
||
v = [@NT(a = 1, b = 2), @NT(a = 1.2, b = 3)] | ||
@test collectcolumns(v) == Columns(@NT(a = Real[1, 1.2], b = Int[2, 3])) | ||
|
||
v = [@NT(a = 1, b = 2), @NT(a = 1.2, b = "3")] | ||
@test collectcolumns(v) == Columns(@NT(a = Real[1, 1.2], b = Any[2, "3"])) | ||
|
||
v = [@NT(a = 1, b = 2), @NT(a = 1.2, b = 2), @NT(a = 1, b = "3")] | ||
@test collectcolumns(v) == Columns(@NT(a = Real[1, 1.2, 1], b = Any[2, 2, "3"])) | ||
end | ||
|
||
@testset "collecttuples" begin | ||
v = [(1, 2), (1, 3)] | ||
@test collectcolumns(v) == Columns((Int[1, 1], Int[2, 3])) | ||
|
||
v = [(1, 2), (1.2, 3)] | ||
@test collectcolumns(v) == Columns((Real[1, 1.2], Int[2, 3])) | ||
|
||
v = [(1, 2), (1.2, "3")] | ||
@test collectcolumns(v) == Columns((Real[1, 1.2], Any[2, "3"])) | ||
|
||
v = [(1, 2), (1.2, 2), (1, "3")] | ||
@test collectcolumns(v) == Columns((Real[1, 1.2, 1], Any[2, 2, "3"])) | ||
end |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this inferable if
eltype(itr)
is concrete or onceT
has become at least as wide as it? That's essential for performance in Basemap
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't have a strong enough intuition to understand what the compiler can optimize. Here Base uses
el isa T || typeof(el) === T
. What should I check exactly to test inferrability? Maybe making this a functionis_fieldwise_subtype(el::S, ::Type{T}) = all((s <: t) for (s, t) in zip(S.parameters, T.parameters))
would help the compiler, I'm not sureThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@code_warntype
will tell you whether the return type is inferred. Using a helper function could indeed help (maybe after marking it asBase.@pure
, but the chances are that I'm wrong).There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've checked with constant
eltype
and now it is tyoe stable. Somehow the way to achieve that was to use a generated function to checkis_fieldwise_subtype
, which we should do anyway for performance. It's not inferrable in theNamedTuples
case (the initialization steparrayof
which we already use inmap
is not inferrable), but I hope all theNamedTuples
business will be much better in 0.7There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still, should probably benchmark it to make sure it's doing OK compared with the inference based
map
...There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's probably a way to achieve the same result without a generated function, but these things are always tricky...