Repository navigation
Status on cloudpickle non-determinism #453
Description
Hello,
@ogrisel mentioned in this comment (#385 (comment)):
Anyway, having deterministic pickles is probably out of scope for cloudpickle so I would be in favor of closing this issue.
However, @ogrisel also pushed a PR (#428) which was released as part of cloudpickle 2.0.0 that tried to address non determinism owing to dictionary ordering.
I wanted to confirm what is the official status of the project regarding non determinism because I am still seeing non deterministic pickles in cloudpickle 2.0.0
Here is the pickletools.dis outputs of a function:
...
2539: ( MARK
2540: \x8c SHORT_BINUNICODE 'correlation_matrix'
2560: \x94 MEMOIZE (as 115)
2561: \x8c SHORT_BINUNICODE 'drifts_annual'
2576: \x94 MEMOIZE (as 116)
2577: \x8c SHORT_BINUNICODE 'initial_prices'
2593: \x94 MEMOIZE (as 117)
2594: \x8c SHORT_BINUNICODE 'volatilities_annual'
2615: \x94 MEMOIZE (as 118)
2616: \x91 FROZENSET (MARK at 2539)
2617: \x94 MEMOIZE (as 119)
...
pickle of a function on second attempt:
...
2539: ( MARK
2540: \x8c SHORT_BINUNICODE 'volatilities_annual'
2561: \x94 MEMOIZE (as 115)
2562: \x8c SHORT_BINUNICODE 'initial_prices'
2578: \x94 MEMOIZE (as 116)
2579: \x8c SHORT_BINUNICODE 'drifts_annual'
2594: \x94 MEMOIZE (as 117)
2595: \x8c SHORT_BINUNICODE 'correlation_matrix'
2615: \x94 MEMOIZE (as 118)
2616: \x91 FROZENSET (MARK at 2539)
2617: \x94 MEMOIZE (as 119)
...
As you can see, the entries are all the same, but shuffled around.
This function is part of a large project, so unfortunately I can't produce a short test case right now.
Notice that kubeflow pipelines implement caching by making sure that pickle of the function hasn't changed. (there is an option to not use pickle as well, but it has its own problems). Having a non deterministic cloudpickle invalidates the cache every time making that feature useless.
Thanks.
Activity
pierreglaser commentedon Oct 26, 2022
The pickle instructions you're displaying seems like reconstruction instruction for
set(more precisely,FrozenSet) instances, which are not ordered (unlike dicts in Python > 3.7). I would imagine that pickles ofsetobjects created bypickle(and notcloudpickle) are also non-deterministic. Not sure if we want to override this behavior (which would in any way work only for theCloudPicklerinheriting from the pure-pythonPickler, and not the fast C-backedPickler).ogrisel commentedon Oct 13, 2023
We could introduce a constructor parameter to implement a slower, deterministic version of cloudpickle. But, indeed I am not sure how we could do that with the subclass of the C-implementation of the CPython
pickle.Picklerclass.Note that
joblib.hashcan do that already, but it does not analyse the content of dynamically defined functions.Support customizing how built-in types are pickled
AdrS commentedon Mar 31, 2025
Apache Beam uses either cloudpickle or dill to save code as part of a workflow graph specification. Google uses Apache Beam with a best-effort cache to avoid starting workflows from scratch after they get interrupted. Increasing the determinism of pickling increases the cache hit rate, saves resources, and avoids delays from starting workflows again from scratch. Apache Beam is transitioning from dill to cloudpickle and would like to contribute two changes to increase the pickling determinism:
Ideally these changes can be part of cloudpickle so Apache Beam can minimize the changes to its vendored copy.
Note: the goal is not to guarantee complete determinism. Mostly-deterministic pickling is useful enough.
Replace random class_tracker_id with sequential integer.
tomMoral commentedon Jul 17, 2025
The
cloudpicklepayload is almost deterministic, except in two known situations:test_dynamic_class_deterministic_roundtrip, which is xfailed for the moment. The identifier is used to map multiple classes unpickled in the same worker to the same class. We should make it dependent on the class definition to make it deterministic. The issue is to make this possible without pickling the code twice. A possible idea would be to use pickle protocol 5 to have the ID of the class as a buffer, which is computed only the first time the class is hashed from the class payload and saved separately.co_filenamecan also change, for instance in jupyter notebooks, as reported in cloudpickle is not stable in notebooks #538. PR MTN deterministic co_filename for dynamic code pickling #560 tries to solve this issue but got stalled due to unstable CI on Windows.