-
Notifications
You must be signed in to change notification settings - Fork 130
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
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 |
src/Groups/gsets.jl
Outdated
@@ -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. |
I just tried to push to this pull request, but somehow this was not successful; I got the message that I can open a new pull request at https://github.com/oscar-system/Oscar.jl/pull/new/GSet_speedup. |
The branch is in @mjrodgers' fork and not in |
Strange, I do have it marked so that "Maintainers are allowed to edit this pull request", which says that "users with write access to oscar-system/Oscar.jl can add new commits to your GSet_speedup branch"...
Let me check if there is something else I need to do.
… On 27. Nov 2024, at 2:00 PM, Thomas Breuer ***@***.***> wrote:
I just tried to push to this pull request, but somehow this was not successful; I got the message that I can open a new pull request at https://github.com/oscar-system/Oscar.jl/pull/new/GSet_speedup.
(Last time when I tried to push to someone else's pull request, this worked.)
—
Reply to this email directly, view it on GitHub <#4307 (comment)>, or unsubscribe <https://github.com/notifications/unsubscribe-auth/AANWIWN6FYGUE2G3FRR6KET2CW67DAVCNFSM6AAAAABRWQDT5GVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDKMBTHAYTSNRSGQ>.
You are receiving this because you were mentioned.
|
I think maybe you need to push directly to my branch instead of to the pull request, Lars Kastner verified that he can push there. |
d365ba5
to
39dfab7
Compare
Now it worked. Thanks for the hints. |
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #4307 +/- ##
==========================================
+ Coverage 84.36% 84.40% +0.04%
==========================================
Files 652 656 +4
Lines 86955 87246 +291
==========================================
+ Hits 73360 73641 +281
- Misses 13595 13605 +10
|
(This is something we cannot decide on the level of types.)
30dddd1
to
72db49d
Compare
@mjrodgers ping didn't you want to push some updates yesterday? |
@fingolfin I have some general timing tests and comparisons between our different orbit methods that I am working on, but nothing to push at the moment (and I don't know that it needs to be tied to this specific pull request), |
This last commit somehow broke history. Iirc you didn't touch 133 files in this PR |
@lgoettgens No, I pulled the changes Thomas made to my local machine, and then everything was strange. I tried to revert my commit, but still everything is not working. I'm trying to figure out what went wrong (actually I'm okay if I don't figure out what went wrong as long as I can fix it). That was very strange, when I pulled those it basically asked me if I wanted to merge my own branch into itself, and then all those files were changed (no idea where those changes came from). Then when I tried to revert it, they were still all changed. I think it's sorted now. |
(This is something we cannot decide on the level of types.)
df7585c
to
a492b17
Compare
@ThomasBreuer I am noticing some inconsistent behavior in my timing tests, for example if I run julia> G = symmetric_group(1000)
Sym(1000)
julia> Omega = gset(G)
G-set of
Sym(1000)
with seeds 1:1000
julia> @benchmark order(stabilizer(Omega, Set([1, 2]))[1])
BenchmarkTools.Trial: 10000 samples with 1 evaluation.
Range (min … max): 77.958 μs … 270.000 ms ┊ GC (min … max): 0.00% … 94.68%
Time (median): 89.000 μs ┊ GC (median): 0.00%
Time (mean ± σ): 122.405 μs ± 2.738 ms ┊ GC (mean ± σ): 25.49% ± 1.60%
▄▆█▆▆▃
▂▁▂▂▁▂▂▂▃▃▄▄▄▃▃▂▂▂▃▄▆████████▆▅▄▃▃▃▃▃▃▃▃▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▁▂ ▃
78 μs Histogram: frequency by time 105 μs <
Memory estimate: 186.04 KiB, allocs estimate: 770. but if I try julia> G = symmetric_group(1000)
Sym(1000)
julia> Omega = gset(G, [[1, 2]]) # action on ordered pairs
G-set of
Sym(1000)
with seeds [[1, 2]]
julia> @benchmark order(stabilizer(Omega, [1, 2])[1]) then it takes quite a long time (I'm not sure it ever actually finishes). Maybe we are somehow not triggering the specialized code in this case? (We can talk about this tomorrow in person, but I figured I would put it here in the pull request also.) |
Yes, the special |
a492b17
to
e13e033
Compare
I think this is ready to merge, we will add more timing tests in a further pull request but we have some basics, we have greatly sped up both orbit and stabilizer computations in most of the basic special cases, |
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).