Repository navigation
perf: reduce arb pickle size by ~50% - #447
deftasparagusanaconda wants to merge 4 commits into
Conversation
use python's native int pickling instead of hexadecimal
|
we can also reduce pickled acbs if we pickle them as
instead of
so we avoid including the |
|
Seems to have failed all the tests. |
|
import pickle
n = 10 ** 10000
for protocol in range(pickle.HIGHEST_PROTOCOL + 1):
try:
pickle.dumps(n, protocol=protocol)
print('protocol', protocol, 'passed')
except Exception as e:
print('protocol', protocol, 'failed')
print(e)the fix is to replace |
|
@oscarbenjamin i see two options moving forward. which do you prefer?
i prefer the first option, because python has used |
|
We can also just not have the change here and use hex. This is why hex as used in the first place. |
|
i dont favour hex because it takes up twice the storage needed. its not uncommon to store thousands of arbs with millions of digits that take up gigabytes of storage. i am currently computing a constant, where i'd like to store 284228 arbs at 100100dps. using hex, that should be roughly (im just trying to prove that the storage savings are significant) |
|
Can it not just use to_bytes for all protocol versions? I don't want to overcomplicate anything here. |
|
👍 sure ill check and see in an hour |
|
i also found that import pickle
from flint import fmpz
n = fmpz(10 ** 10000)
for protocol in range(pickle.HIGHEST_PROTOCOL + 1):
try:
pickle.dumps(n, protocol=protocol)
print('protocol', protocol, 'passed')
except Exception as e:
print('protocol', protocol, 'failed')
print(e)we will have to fix any type that pickles ints |
using int.to_bytes() and int.from_bytes() instead of native int pickling fmpz still does not support it. fix later.
|
this new version may be harder to maintain |
since tests didnt pass for 3.10
|
protocols 0 & 1 are still inefficient, because they cant pickle bytes efficiently. i wont improve this import math, pickle
from flint import arb, ctx
ctx.dps = 1_000_000
for protocol in range(pickle.HIGHEST_PROTOCOL + 1):
original = arb(2).sqrt().mid()
pickled = pickle.dumps(original, protocol=protocol)
roundtrip = pickle.loads(pickled)
limit = math.ceil(ctx.dps * math.log2(10) / 8)
assert original == roundtrip
print('protocol :', protocol)
print('pickle size :', len(pickled))
print('theoretical limit:', limit)
print('difference :', len(pickled) - limit)
print()
# protocol : 0
# pickle size : 455727
# theoretical limit: 415242
# difference : 40485
#
# protocol : 1
# pickle size : 622855
# theoretical limit: 415242
# difference : 207613
#
# protocol : 2
# pickle size : 415294
# theoretical limit: 415242
# difference : 52
#
# protocol : 3
# pickle size : 415294
# theoretical limit: 415242
# difference : 52
#
# protocol : 4
# pickle size : 415311
# theoretical limit: 415242
# difference : 69
#
# protocol : 5
# pickle size : 415311
# theoretical limit: 415242
# difference : 69 |
previously, we stored the 4 integers of a pickled arb in hexadecimal. thats 2 bytes per byte. instead, we use python's native int pickling, achieving near-optimal packing
old:
new:
69 haha nice