-
-
Notifications
You must be signed in to change notification settings - Fork 31.1k
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
Asymptotically faster divmod and str(long) #47701
Comments
A few weeks ago, I blogged about taking advantage of Karatsuba http://fredrik-j.blogspot.com/2008/07/making-division-in-python-faster.html To summarize, this method blows the builtin division out of the water The primary catch is that the result of the Newton division may be A pure Python implementation of divmod, with error correction based on http://www.dd.chalmers.se/~frejohl/code/libarith/libarith.py (See the function idivmod) Of particular note is that fast divmod gives a fast way to do radix >>> from time import clock
>>> a = 2**1257787-1
>>> t1=clock(); s1=str(a); t2=clock(); t2-t1
109.08065159119386
>>> t1=clock(); s2=numeral(a); t2=clock(); t2-t1
7.1394886780303182
>>> s1 == s2
True (This recursive algorithm, by the way, is actually faster than str() Would there be any interest in porting these algorithms to C and using There are likely some problems that I have overlooked. A critical review |
Yes, definitely! Though it depends a little bit how much complication A subquadratic algorithm for converting strings to longs might also fit Now I'm just waiting for you to propose an implementation of integer |
Not that much, I think, the pure Python version being just a few lines
Yes, there is also code for fast (O(M(n)) integer square roots in |
For your convenience, I have split the division and numeral code off to I also updated the remainder logic to use the default divmod instead of |
And here some timings on my laptop. Both int->str and balanced division become faster somewhere between 1000 |
There's also the recursive division algorithm due I had a Python implementation of this somewhere; Assigning this to me so that it doesn't get lost or |
See also bpo-1746088. |
Here's a pure Python implementation of the Burnikel and Ziegler recursive The original paper describing the algorithm is available here: |
Oops. Wrong file. Here's the right one. |
Indeed, that seems to be much faster. In the mean time, do you mind if I |
Not at all! I guess constant factors could well appear and/or disappear when There are some semi-obvious tricks available that might speed up the |
I have translated in C the algorithm for long division by Here is a benchmark for divmod(p. q), p = 7**np, q = 5**nq BZ starts being faster than Python division around 2000 bits, apart The treatment of exceptions is very rudimentary; Please find attached the diff to the longobject.c file in Python-2.6b3 . Mario |
Thanks for the patch, Mario! I'll give a look when I get the chance. |
In this patch I added to the patch by Mark in bpo-3944 the code Benchmark for division on Athlon 64 3800+ with respect to Python3.0: |
The longobject2.diff patch probably doesn't apply cleanly any more. I think this patch looks like a promising beginning, but there's still (1) the huge numbers of Py_DECREFs and Py_XDECREFs. Some refactoring (2) I suspect that many of the operations could be turned into in-place I'm not yet 100% sold on getting subquadratic division into Python---it |
In this patch there is an implementation of the algorithm to convert |
In this second patch to the above patch it is added the recursive Here is a benchmark on hp pavilion Q8200 2.33GHz str(n) in the first patch uses a quadratic algorithm, but asymptotically |
Unassigning myself for now. The most recent patch still needs work before it can be considered for inclusion. |
See also bpo-18107, in particular http://mail.python.org/pipermail/pypy-dev/2013-May/011433.html. |
As bpo-18107 has been closed as a duplicate of this, should this be moved to open from languishing? |
FWIW, we have implemented a faster algorithm for divmod for big numbers using Mark's fast_div.py in PyPy. In particular, this speeds up str(long) for large numbers significantly (eg calling str on the result of math.factorial(2**17) is now 15x faster than CPython ;-)). |
Urk! I hope your implementation included a healthy dose of validation, testing and cleanup. :-) (I have no doubts that it did.) I'd consider fast_div.py to be proof-of-concept code rather than something suitable for immediate use. |
yes, that sounds fair. In PyPy we improve things occasionally if somebody feels like working on it, but in general competing against GMP is a fools errand. |
Python has a reasonable efficiency up to 1000 decimal digits (according to benchmark) which is already really great! Operations with more than 1000 decimal digits is an uncommon. IMO you should use a dedicated library like GMP for that. I would prefer to keep CPython code simple enough to maintain. Objects/longobject.c is already 5744 lines of C code. longformat_BZ.diff adds around 700 lines of code, but it only makes str(int) starting at 2000 decimal digits. Yeah, we could do better for integers with <many digits>, but I would prefer not to :-) Python has a limited number of volunteers working on it, and it's not specialized in numbers. We should keep the maintenance burden at an acceptable level ;-) |
Ha! This will never die. More discussion in bpo-46558. Ya, I already closed it, but don't want to. I opened it to begin with to record an int->str method that doesn't use division, so it didn't really belong on this report. What if we _didn't_ convert these things to C? That's the primary question the new report gets around to asking. These things are far easier to write, understand, and maintain in Python, and converting to C is generally only improving a constant factor, or _maybe_ removing a log(n) factor. When we're looking at massive O() improvements, squeezing those out is of comparatively little value. |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: