-
-
Notifications
You must be signed in to change notification settings - Fork 528
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
Integer * int is slow #6199
Comments
comment:2
We could make an action on Integers by ints. |
comment:3
So sadly, I think this is a wontfix. I tested this out, and at the expense of some ugly code, we get roughly a factor of 2 speedup -- and that's basically the best we can do. The problem is that the coercion model needs to look up a cached map to avoid the coercion to Fredrik, did you have code that was getting slowed down by this? Would a factor of two on this make a big difference for you? |
comment:4
Craig, thanks for investigating. This is, unfortunately, quite critical for improving mpmath's performance, and the only other solution is not to use sage.Integer. I haven't touched Cython in a while now, but... I'm still not clear about why Integer multiplication has to go through the generic ring multiplication code. Wouldn't it be possible to extend the coercion/operator code so that any subclass can overload it? Something like (in regular Python, made-up method names):
|
comment:5
Hi Fredrik, Well, let's not give up hope yet. :) I'll give the full explanation of what's happening with the coercion system below, but first, I want to ask: is there any reason you couldn't just switch to using Also, I want to note that there's one more reason to not worry so much: arithmetic on Python Here's what's happening with this code. Every object that derives from Sage's
happen without any hard work on the part of the user, and with a minimal amount of code duplication. So what you're suggesting above does in fact happen: the
So what's happening right now is that we're hitting the third bullet, i.e. we end up doing the coercion of the Now, that's saying that the "right" fix, i.e. use the coercion model the way it's intended, doesn't work out. Of course, that doesn't mean we don't have other options. I just sat down and hacked together a little code that short-circuits things earlier on (just before the second bullet above). It definitely works ... here's before:
and after:
In the case that it's not (Side note: I got a ~10% performance regression on the Robert, what are your thoughts? I know that "Special cases aren't special enough to break the rules," and in general I don't like special-casing things. Plus, it's potentially less significant with Py3 on the horizon. But if it's really going to be a showstopper for Fredrik, we should at least think about it more. It's not like there are very many types where the operations are noticeably faster than a few lookups, so it's not opening a loophole that could be abused very much, I think. |
comment:6
If we're going to special case, we could override Note that
so I wrote my own
With this, I did a special _mul_long method. Before:
After:
I'm leaning towards it being worth it, on the right only, for * and + only. The cost is (on my machine) an extra 25ns per non-identical-parents operation, which are at the cheapest is at least 100s of ns. |
comment:7
Thanks for working on this! In mpmath, there are a lot of loops for fixed-point power series that basically look something like:
Because Python ints are significantly faster than Integers for small values and Integers are significantly faster than ints for large values, it's optimal to use counter_type = int and value_type = Integer. (It's even more optimal to Cythonize the same code, but I'm not there quite yet.) Shift and division were already fixed.
Unfortunately I think it's equally common for the int to be on the left (this can be fixed, but it's hard to track down where it happens). Addition is not as important. |
comment:8
So what is the milestone for this ticket? Is it still a "wontfix"? |
comment:9
Robert: I think there are several places we could put the code -- if nothing else, it might be nice to keep it in Also, I'd prefer to just go ahead and implement it for arithmetic on both sides -- we can do two type comparisons as I suspect you're going to be on campus in a few hours -- we can chat about this then. Fredrik: That's a really good use-case. That said, I guess I don't understand why GMP/MPIR don't use unboxed immediate integers for small values, but given that I haven't played with the guts of the code, they probably know better than I do. It would be nice in your case, though -- you could have both I'm curious: is this code going to be used as part of the "core" of mpmath, or will you just write the code so it takes advantage of Sage whenever it's available? (My impression was that you liked mpmath being pure Python.) |
comment:10
Multiplication on the left has less to gain, as it's going to try to call int.mul before falling back to this code. Do you think it's worth doubling the general case penalty to support a smaller relative gain? People who care about timings this small (e.g. mpmath) can follow such rules, or ideally write Cython directly. I wrote a mode once that was verbose about all the coercions used, I could resurrect that somewhere for more easily tracking down stuff like this. FWIW, I put |
comment:11
Craig:
This is actually on MPIR's list of "development ideas"; I think the only reason it isn't supported is that no one has written the code yet. Still, there are reasons to keep using Python ints: ints are a bit faster than custom types because they are special-cased in various places in the Python interpreter, and JITs can optimize them (psyco does a decent job with mpmath partly because of this -- maybe in the future we'll also have Unladen Swallow and PyPy).
It already uses sage.Integer when it's available. Since the core is fairly complex (and hence difficult to optimize), I've recently split everything cleanly into "core" and "high level" code. All the high level code can easily use different cores (or "contexts"). There is now both the standard multiprecision context, and a fully working machine-precision context (using float/complex) implemented in less than 300 lines of code. It should be possible to implement a light wrapper of Sage's real and complex numbers in close to 300 lines so that Sage can use all the high-level functions in mpmath "natively". Still, since Sage's numbers don't provide quite the same features as mpmath's core, it remains necessary to continue optimizing mpmath's core as well. This will eventually have to be done by rewriting more of it in Cython (already a few Cython helper functions are imported from Sage when available). But for now, fixing basic inefficiencies in the present code (such as this issue) seems worthwhile IMHO. |
comment:12
Robert -- looks good, just needs some doctests. |
comment:13
Oh, and so I don't forget -- we also seemed to get a consensus that people wanted |
Attachment: 6199-fast-int-mul.patch.gz |
comment:14
OK, I've uploaded a new patch. |
comment:15
Looks good. One question, though: why do a test and use |
oops, I tested with this fix but forgot to check it in |
comment:16
Attachment: 6199-fast-mul-fix.patch.gz I applied this and got roughly a 15% speedup for mpmath's test suite, with everything seemingly working, so +1 from me. |
apply only this patch |
comment:17
Attachment: 6199-fast-int-mul-all.patch.gz Attached a new patch which cleans up subtraction and note about corner case. |
Author: Robert Bradshaw |
comment:19
The changes look good. |
Reviewer: Fredrik Johannson, Mike Hansen |
Merged: sage-4.3.3.alpha0 |
Changed reviewer from Fredrik Johannson, Mike Hansen to Fredrik Johansson, Mike Hansen |
Changed reviewer from Fredrik Johansson, Mike Hansen to Fredrik Johansson, Mike Hansen, Craig Citro |
Ditto for +, -. If I understand the code correctly, there always is a coercion to Integer, which could be avoided. I'm not sure how to best fix this since the ring operators are not implemented in the Integer class itself.
For division and shift, see #6083 and #6118.
CC: @robertwb
Component: basic arithmetic
Author: Robert Bradshaw
Reviewer: Fredrik Johansson, Mike Hansen, Craig Citro
Merged: sage-4.3.3.alpha0
Issue created by migration from https://trac.sagemath.org/ticket/6199
The text was updated successfully, but these errors were encountered: