OILS / opy / old / determinism.sh View on Github | oilshell.org

112 lines, 31 significant
1#!/usr/bin/env bash
2#
3# 2018 experiments on determism. There are 2017 experiments in compare.sh and
4# misc/determinism.py.
5#
6# I think I fixed the misc.Set() bug in OPy, but there still remained CPython
7# determinism. However I haven't reproduced it on a small case.
8#
9# Usage:
10# ./determinism.sh <function name>
11
12set -o nounset
13set -o pipefail
14set -o errexit
15
16# Trying to reproduce problem with pyassem.py and Block() in order_blocks, but
17# this does NOT do it.
18# I had to add sorted() to make it stable there, but here I do not? Why?
19
20# See also: https://github.com/NixOS/nixpkgs/issues/22570
21#
22# "No, the sets are built as real sets and then marshalled to .pyc files in a
23# separate step. So on CPython an essentially random order will end up in the
24# .pyc file. Even CPython 3.6 gives a deterministic order to dictionaries but
25# not sets. You could ensure sets are marshalled in a known order by changing
26# the marshalling code, e.g. to emit them in sorted order (on Python 2.x; on
27# 3.x it is more messy because different types are more often non-comparable)."
28#
29# Is that accurate? The issue here is not sets as marshalled constants; it's
30# USING sets in the compiler.
31#
32# set([1, 2, 3]) and {'a': 'b'} do not produce literal constants!
33
34dictset() {
35 local n=${1:-30}
36 local python=${2:-python}
37
38 seq $n | $python -c '
39import sys
40class Block:
41 def __init__(self, x):
42 self.x = x
43 def __repr__(self):
44 return str(self.x)
45
46s = set()
47hashes = []
48for line in sys.stdin:
49 b = Block(line.strip())
50 hashes.append(hash(b))
51 s.add(b)
52print s
53print hashes
54'
55}
56
57dictset2() {
58 local n=${1:-30}
59 local python=${2:-python}
60
61 seq $n | $python -c '
62import sys
63d = {}
64s = set()
65for line in sys.stdin:
66 i = line.strip()
67 d[i] = 1
68 s.add(i)
69print "D", " ".join(d.keys())
70print "S", " ".join(s)
71'
72}
73
74# Each iteration is stable.
75compare-iters() {
76 for i in $(seq 10); do
77 # Run it twice with the same seed
78 dictset
79 done
80}
81
82# Changing the seed changes the order.
83
84# Aha! hash(Block()) is still not deterministic with a fixed seed, because it
85# uses the address?
86#
87# https://stackoverflow.com/questions/11324271/what-is-the-default-hash-in-python
88
89compare-seed() {
90 for seed in 1 2 3; do
91 echo "seed = $seed"
92 # Run it twice with the same seed
93 PYTHONHASHSEED=$seed $0 dictset
94 PYTHONHASHSEED=$seed $0 dictset
95 done
96}
97
98# Hm this is stable oto.
99compare-python() {
100 for i in $(seq 10); do
101 dictset
102 dictset '' ../_devbuild/cpython-full/python
103 done
104}
105
106#
107# OPy
108#
109
110# See smoke.sh
111
112"$@"