-
Notifications
You must be signed in to change notification settings - Fork 129
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
Speed up orbits of permutation groups on integers #4307
base: master
Are you sure you want to change the base?
Conversation
@ThomasBreuer If you can take a look. At the moment I am only mapping |
What about other places passing an action function to GAP? |
I don't think there are any, when I checked. We don't currently experience any slowdown like this when calling |
I think we have to distinguish two situations:
|
Do we have a better idea than keeping the generic |
7d51976
to
b0547de
Compare
Tests fail. Also what this really is missing is some systematic benchmark tests, so that we can verify each change for how it affects performance. Also, could you please share your example that where this PR makes it go from a 6x to a 2x slow down? |
I've added a new test to specifically catch the error (which was previously thrown outside of a |
Working to put together some systematic benchmarks, but for this specific case we have julia> G = symmetric_group(5)
Sym(5)
julia> @benchmark Vector{Int}(GAP.Globals.Orbit(G.X,1))
BenchmarkTools.Trial: 10000 samples with 10 evaluations.
Range (min … max): 1.700 μs … 4.329 μs ┊ GC (min … max): 0.00% … 0.00%
Time (median): 1.829 μs ┊ GC (median): 0.00%
Time (mean ± σ): 1.844 μs ± 86.960 ns ┊ GC (mean ± σ): 0.00% ± 0.00%
▁▄▆█▇▅▆
▂▂▂▂▂▃▃▄▇▇███████▇▆▅▅▅▄▄▅▃▃▃▃▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▁▂▂▂▂▂▂▂▂▂ ▃
1.7 μs Histogram: frequency by time 2.21 μs <
Memory estimate: 1.09 KiB, allocs estimate: 28. With this pull request: julia> @benchmark collect(orbit(G,1))
BenchmarkTools.Trial: 10000 samples with 8 evaluations.
Range (min … max): 3.688 μs … 8.714 μs ┊ GC (min … max): 0.00% … 0.00%
Time (median): 4.146 μs ┊ GC (median): 0.00%
Time (mean ± σ): 4.167 μs ± 195.265 ns ┊ GC (mean ± σ): 0.00% ± 0.00%
▄▇▄█▇▆▆▆▇▃▂
▁▁▁▂▂▂▃▃▂▂▂▂▂▂▃▅█████████████▅▇▅▄▃▃▂▂▂▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁ ▃
3.69 μs Histogram: frequency by time 4.89 μs <
Memory estimate: 3.92 KiB, allocs estimate: 91. This 2x slowdown is consistent when using larger |
@@ -351,8 +362,8 @@ julia> length(orbit(Omega, 1)) | |||
""" | |||
function orbit(Omega::GSetByElements{<:GAPGroup, S}, omega::S) where S | |||
G = acting_group(Omega) | |||
acts = GapObj(gens(G)) | |||
gfun = GapObj(action_function(Omega)) | |||
acts = GapObj(gens(G); recursive=true) |
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.
acts = GapObj(gens(G); recursive=true) | |
acts = [GapObj(g) for in gens(G)] |
but even this will fail if g
cannot be converted to a GAP object...
Sorry if my comment above ("I think we have to distinguish two situations.") was not clear enough. What I wanted to say is that in the current setup, we need first of all one generic In addition to that method, we can install more |
This still fails all its tests. @mjrodgers what's the status there, are you working on it? Regarding the benchmarks: the first example actually suffers from inefficient code for converting a GAP list of integers into a Also type instability hurts this micro benchmark. To wit:
Of course this is minor and it equally affects the Oscar wrapper for GAP's For that, as @ThomasBreuer already pointed out, and as we discussed a few days ago, you'll probably need a different strategy: E.g. it only makes sense to use the "the underlying GAP objects of the group generators" if the given group actually is a GAP group (which the method signature already ensures), and the objects being acted on are "native" GAP objects -- which right now probably means only for To unwrap the generators it is probably more efficient to use
|
Next I wonder how expensive storing the orbit as an attribute is -- this potentially allocates a fresh |
Working with Thomas on it, this pull request might end up being superseded by the solution that Thomas describes in his previous comment; but I wanted to at least include this additional test here, since it can help track an extra "weird" case that might need some extra care. |
Shall I make a new pull request that adds some special |
I think it is good to add to the current pull request, if that is easy. |
This aims to address issue #3287 by letting GAP know when we are in certain special cases which have optimized GAP methods for computing orbits.
Computing the orbit of a single point seems to still be slower than calling GAP directly by about a factor of 2, but this is a big improvement to the previous case (where it was about a 6x slowdown).