gh-157742: Check for signals every 64th iteration in the int arithmetic loops - #157744
eendebakpt wants to merge 3 commits into
Conversation
x_mul() checked for signals on every row, x_divrem() on every quotient digit and the decimal string conversion on every digit. PyErr_CheckSignals() costs about as much as a hundred digit operations, so for small operands (a 2-digit divisor, a 10x10 product) the checks cost more than the arithmetic. SIGCHECK() now takes the loop index and checks on every 64th iteration. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
Could you test pidigits on this pr? |
pidigits is in the noise (although on a quiet machine one can measure the improvement I believe). With the same script as above one can see that also the multiplication of 64-bits ints gains.
|
| @@ -0,0 +1 @@ | |||
| Improve performance of arithmetic operations like multiplication and division for :class:`int`. | |||
There was a problem hiding this comment.
This affects also string conversion.
There was a problem hiding this comment.
Yes, but the gain is not really worth mentioning. For small number of digits the overhead dominates, for large number of digits the bigint algorithm in _pylong takes over.
There was a problem hiding this comment.
On your benchmarks: 1.10x speedup, no? Looks too big for noise.
There was a problem hiding this comment.
I benchmarked again on another system, not a factor 1.04 so it is not noise. But conversion to string is mostly relevant for small strings and the gain there very small (due to construction of the str object), For very large objects another code path is used (_pylong).
|
For systems under duress, how long should we wait when doing a ctrl+c for Python to exit properly (is it visible?) Note to myself and for others in general but did we audit other parts of the code where we spent long calculations without checking for signals? I never really considered this problem but I wonder if hashlib in general should not check that when doing hashing per large blocks. I never worked with the check signal API so I do not know when this applies as well (if we are not holding the GIL should we check for signals?) |
With the 64-row batch, Karatsuba base cases (36-70 rows) mostly never reached the check, so e.g. a 200k-digit product ran for seconds without handling a signal. A 32-row batch makes every substantial base case check, and k_mul() additionally checks once per recursion step. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The signal checks are not done everywhere consistently. It is not present in For I updated the PR to add a signal check to A parallel approach is to improve the performance of the signal check itself. That is done in #157748. |
x_mul()checks for signals on every row,x_divrem()on every quotient digit and the decimal string conversion on every digit.PyErr_CheckSignals()costs about as much as a hundred digit operations, so for small operands the checks cost more than the arithmetic.SIGCHECK()now takes the loop index and checks on every 64th iteration, the same pattern_sreuses.Benchmark script
Generated with Claude Code