Skip to content

Convert mpz to heap type#195

Closed
skirpichev wants to merge 1 commit into
diofant:masterfrom
skirpichev:heap-type
Closed

Convert mpz to heap type#195
skirpichev wants to merge 1 commit into
diofant:masterfrom
skirpichev:heap-type

Conversation

@skirpichev

@skirpichev skirpichev commented Jul 13, 2025

Copy link
Copy Markdown
Member

Closes #351

@skirpichev

Copy link
Copy Markdown
Member Author
Benchmark 3.13-ref 3.13-patch
(mpz(1<<7))**2 273 ns 330 ns: 1.21x slower
(mpz(1<<38))**2 274 ns 326 ns: 1.19x slower
(mpz(1<<300))**2 340 ns 392 ns: 1.15x slower
(mpz(1<<3000))**2 3.75 us 3.92 us: 1.05x slower
Geometric mean (ref) 1.15x slower
Benchmark 3.14-ref 3.14-patch
(mpz(1<<7))**2 254 ns 315 ns: 1.24x slower
(mpz(1<<38))**2 254 ns 315 ns: 1.24x slower
(mpz(1<<300))**2 323 ns 381 ns: 1.18x slower
(mpz(1<<3000))**2 3.82 us 3.96 us: 1.03x slower
Geometric mean (ref) 1.17x slower
Details
$ echo $CFLAGS 
-std=c11 -Wall -Wpedantic -Werror -O3
$ python3.13 -c "import sysconfig; print(sysconfig.get_config_var('CONFIG_ARGS'))"
'--enable-optimizations' '--with-system-libmpdec'
# bench.py
from operator import mul

import gmp
import pyperf


runner = pyperf.Runner()
for v in ["1<<7", "1<<38", "1<<300", "1<<3000"]:
    i = eval(v)
    bn = "(mpz("+v+"))**2"
    x = gmp.mpz(i)
    runner.bench_func(bn, mul, x, x)

@skirpichev skirpichev closed this Jul 18, 2025
@skirpichev
skirpichev deleted the heap-type branch July 18, 2025 01:18
@skirpichev
skirpichev restored the heap-type branch July 26, 2025 06:08
@skirpichev skirpichev reopened this Jul 26, 2025
@skirpichev
skirpichev force-pushed the heap-type branch 2 times, most recently from 9f3dbc6 to 871829c Compare July 27, 2025 03:22
@skirpichev
skirpichev force-pushed the heap-type branch 3 times, most recently from ab3ed5a to 7214077 Compare July 27, 2025 14:53
@skirpichev skirpichev closed this Jul 27, 2025
@skirpichev
skirpichev deleted the heap-type branch July 27, 2025 15:38
@skirpichev
skirpichev restored the heap-type branch July 30, 2025 02:29
@skirpichev skirpichev reopened this Jul 30, 2025
@skirpichev skirpichev closed this Aug 3, 2025
@skirpichev
skirpichev deleted the heap-type branch August 3, 2025 07:46
@skirpichev
skirpichev restored the heap-type branch August 5, 2025 04:01
@skirpichev skirpichev reopened this Aug 5, 2025
@skirpichev

Copy link
Copy Markdown
Member Author

Another benchmark:

Benchmark ref heap-type
collatz(97) 124 us 169 us: 1.37x slower
collatz(871) 186 us 255 us: 1.37x slower
Geometric mean (ref) 1.37x slower
# bench.py
import pyperf
from gmp import mpz

zero = mpz(0)
one = mpz(1)
two = mpz(2)
three = mpz(3)

# https://en.wikipedia.org/wiki/Collatz_conjecture
def collatz(n):
    total = zero
    n = mpz(n)
    while n > 1:
        n = n*three + one if n & one else n//two
        total += one
    return total

runner = pyperf.Runner()
for i in [97, 871]:
    h = f"collatz({i})"
    runner.bench_func(h, collatz, i)

@skirpichev skirpichev closed this Aug 5, 2025
@skirpichev
skirpichev deleted the heap-type branch August 5, 2025 04:21
@skirpichev
skirpichev restored the heap-type branch August 16, 2025 11:09
@skirpichev
skirpichev force-pushed the heap-type branch 2 times, most recently from fbc08c5 to ea00e09 Compare February 2, 2026 04:48
@skirpichev skirpichev closed this Feb 2, 2026
@skirpichev
skirpichev deleted the heap-type branch February 2, 2026 07:17
@skirpichev
skirpichev restored the heap-type branch April 13, 2026 04:34
@skirpichev skirpichev reopened this Apr 13, 2026
@skirpichev skirpichev closed this Apr 13, 2026
@skirpichev
skirpichev deleted the heap-type branch April 13, 2026 15:26
@skirpichev
skirpichev restored the heap-type branch June 16, 2026 06:39
@skirpichev skirpichev reopened this Jun 16, 2026
@skirpichev skirpichev closed this Jun 18, 2026
@skirpichev
skirpichev deleted the heap-type branch June 18, 2026 16:37
@skirpichev
skirpichev restored the heap-type branch July 9, 2026 05:25
@skirpichev skirpichev reopened this Jul 9, 2026
@skirpichev
skirpichev force-pushed the heap-type branch 2 times, most recently from 0b815ab to ff41857 Compare July 9, 2026 05:53
@skirpichev

Copy link
Copy Markdown
Member Author

It's worse on PyPy as well, with bench/collatz.py:

collatz0(97): Mean +- std dev: [ref] 356 us +- 58 us -> [heap] 423 us +- 59 us: 1.19x slower
collatz0(871): Mean +- std dev: [ref] 539 us +- 90 us -> [heap] 648 us +- 94 us: 1.20x slower
collatz0((1<<128)+31): Mean +- std dev: [ref] 2.59 ms +- 0.45 ms -> [heap] 3.22 ms +- 0.48 ms: 1.25x slower
collatz1(97): Mean +- std dev: [ref] 547 us +- 75 us -> [heap] 662 us +- 79 us: 1.21x slower
collatz1(871): Mean +- std dev: [ref] 808 us +- 82 us -> [heap] 1.05 ms +- 0.13 ms: 1.30x slower
collatz1((1<<128)+31): Mean +- std dev: [ref] 4.05 ms +- 0.71 ms -> [heap] 5.01 ms +- 0.72 ms: 1.24x slower
collatz2(97): Mean +- std dev: [ref] 398 us +- 58 us -> [heap] 486 us +- 63 us: 1.22x slower
collatz2(871): Mean +- std dev: [ref] 613 us +- 94 us -> [heap] 727 us +- 95 us: 1.19x slower
collatz2((1<<128)+31): Mean +- std dev: [ref] 2.99 ms +- 0.49 ms -> [heap] 3.65 ms +- 0.51 ms: 1.22x slower

Geometric mean: 1.22x slower

@skirpichev skirpichev closed this Jul 9, 2026
@skirpichev
skirpichev deleted the heap-type branch July 9, 2026 10:57
@skirpichev
skirpichev restored the heap-type branch July 17, 2026 05:27
@skirpichev
skirpichev deleted the heap-type branch July 19, 2026 08:29
@skirpichev

Copy link
Copy Markdown
Member Author

With this patch:

diff --git a/gmp.c b/gmp.c
index 4f2d94c..7da0d8e 100644
--- a/gmp.c
+++ b/gmp.c
@@ -34,7 +34,6 @@ MPZ_new(gmp_state * state, PyTypeObject *type)
         res = global.freelist[--global.freelist_size];
         (void)zz_set(0, &res->z);
         Py_INCREF((PyObject *)res);
-        PyObject_GC_Track((PyObject *)res);
     }
     else {
 #endif
@@ -609,7 +608,6 @@ dealloc(PyObject *self)
     MPZ_Object *u = (MPZ_Object *)self;
     PyTypeObject *type = Py_TYPE(self);
 
-    PyObject_GC_UnTrack(self);
 #ifdef ON_CPYTHON
 
     gmp_state *state = get_state(type);
@@ -622,6 +620,7 @@ dealloc(PyObject *self)
     }
     else {
 #endif
+        PyObject_GC_UnTrack(self);
         zz_clear(&u->z);
 
         freefunc tp_free = PyType_GetSlot(type, Py_tp_free);

it's noticeably better:

Benchmark ref heap0 heap3
collatz0(97) 86.9 us 134 us: 1.54x slower 119 us: 1.37x slower
collatz0(871) 131 us 201 us: 1.53x slower 178 us: 1.36x slower
collatz0((1<<128)+31) 681 us 1.02 ms: 1.50x slower 915 us: 1.34x slower
collatz1(97) 105 us 156 us: 1.49x slower 137 us: 1.31x slower
collatz1(871) 158 us 234 us: 1.48x slower 206 us: 1.30x slower
collatz1((1<<128)+31) 810 us 1.21 ms: 1.49x slower 1.06 ms: 1.30x slower
collatz2(97) 88.5 us 132 us: 1.50x slower 117 us: 1.32x slower
collatz2(871) 133 us 198 us: 1.49x slower 175 us: 1.32x slower
collatz2((1<<128)+31) 677 us 1.01 ms: 1.49x slower 894 us: 1.32x slower
Geometric mean (ref) 1.50x slower 1.33x slower

Though, I'm not sure it's a correct approach, see skirpichev/cpython#16.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Make mpz a heap type?

1 participant