File size: 7,048 Bytes
8604228
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#!/bin/sh
# OB-1b: stand up the ob1b engine build.
#
# WHY THIS IS NOT A PLAIN FRESH BUILD. The landed OB-1 build
# (/root/rs053/llama.cpp/build, branch ob1 head c087083) is configured with
# GGML_CUDA=ON, so a from-scratch reconfigure recompiles several hundred nvcc
# translation units (measured: still grinding through
# ggml-cuda/template-instances after 3 minutes at -j4) for a change of ONE
# character in one CPU-side source file. This script instead copies the landed
# build tree into the ob1b worktree, rewrites the absolute source paths inside
# it, lets cmake regenerate its makefiles against the new source root, and then
# recompiles ONLY the translation units that actually changed.
#
# THE SOUNDNESS CHECK IS PHASE A, AND IT IS NOT TAUTOLOGICAL. Phase A touches
# src/ob1-lease.cpp with its CONTENT UNCHANGED and runs make. That genuinely
# recompiles that translation unit in the new tree and relinks libllama.so and
# llama-perplexity. The results are then compared by sha256 against the landed
# binaries. A match proves the copied object tree plus this toolchain reproduce
# the landed engine byte for byte, so that after phase B the ONLY thing
# separating the ob1b binary from the ob1 binary is the one-line guard change.
# A mismatch is reported literally, not worked around.
set -e

SRC=/root/rs053/llama.cpp
DST=/root/ob1b/llama.cpp
LEASE=$DST/src/ob1-lease.cpp

echo "=== OB1B BUILD ==="
echo "utc_start $(date -u +%Y-%m-%dT%H:%M:%SZ)"

# This script must be re-runnable. Restore src/ob1-lease.cpp to its pristine
# c087083 content first, so that phase A always compiles UNPATCHED source no
# matter how many times the script has run before. (Found the hard way: a second
# invocation reused the already-patched file left by the first, which would have
# made phase A compare the patched build against the landed one and call the
# guard change a build-system artefact.)
echo "--- restore pristine source ---"
git -C $DST checkout -- src/ob1-lease.cpp
git -C $DST status --short
echo "guard line as checked out:"
grep -n "OB1_K=%d out of range" $LEASE

echo "--- landed binaries (the reference) ---"
sha256sum $SRC/build/bin/llama-perplexity $SRC/build/bin/libllama.so

echo "--- copy build tree ---"
rm -rf $DST/build
cp -a $SRC/build $DST/build

echo "--- rewrite absolute source paths in text files only (grep -I skips binaries) ---"
echo "text files referencing old source dir: $(grep -rlI "$SRC" $DST/build | wc -l)"
grep -rlI "$SRC" $DST/build | xargs sed -i "s|$SRC|$DST|g"
echo "remaining after rewrite: $(grep -rlI "$SRC" $DST/build | wc -l)"

echo "--- cmake reconfigure against the new source root ---"
# -ffile-prefix-map is what makes phase A an EXACT check rather than an
# approximate one. Source files embed their own path through __FILE__ (llama.cpp
# uses it in its assert macros), so a translation unit recompiled under
# /root/ob1b/... would differ from the landed /root/rs053/... object in that
# string alone -- a benign difference, but one that would leave phase A unable
# to say "byte for byte". Measured on the first attempt of this script, without
# the flag: landed libllama.so carried 151 occurrences of "rs053/llama.cpp" and
# the rebuilt one carried 150 plus 1 occurrence of "ob1b/llama.cpp", exactly the
# one recompiled translation unit. The flag maps the new root back to the old
# one for embedded paths only; it changes no code generation.
cmake -S $DST -B $DST/build -DCMAKE_CXX_FLAGS="-ffile-prefix-map=$DST=$SRC" \
    > /root/ob1b/cmake-reconf.log 2>&1 || {
  echo "CMAKE RECONFIGURE FAILED, log verbatim:"; cat /root/ob1b/cmake-reconf.log; exit 1; }
tail -3 /root/ob1b/cmake-reconf.log

echo "--- age the checked-out sources so make does not rebuild all 392 objects ---"
# git worktree add stamped every checked-out file with the checkout time, which
# is newer than every copied .o; and the sed above bumped every makefile. Both
# would make make rebuild the world. The objects were compiled from byte-
# identical sources at the same commit, so reusing them is sound -- and phase A
# is the check that proves it rather than assuming it.
find $DST -path $DST/build -prune -o -type f -print | xargs -r touch -d "2020-01-01 00:00:00"
sleep 1
find $DST/build \( -name "*.o" -o -name "*.a" -o -name "*.so" -o -name "*.so.*" \) -print | xargs -r touch
find $DST/build/bin -type f -print | xargs -r touch
sleep 1

echo "--- confirm the tree is now fully up to date (make should have nothing to do) ---"
nice -n 10 make -C $DST/build llama-perplexity -j4 2>&1 | tail -5

echo "=== PHASE A: recompile ob1-lease.cpp UNCHANGED, must reproduce the landed binaries ==="
touch $LEASE
nice -n 10 make -C $DST/build llama-perplexity -j4 2>&1 | tail -12
echo "--- phase A digests ---"
sha256sum $DST/build/bin/llama-perplexity $DST/build/bin/libllama.so
A1=$(sha256sum $SRC/build/bin/llama-perplexity | cut -d" " -f1)
A2=$(sha256sum $DST/build/bin/llama-perplexity | cut -d" " -f1)
B1=$(sha256sum $SRC/build/bin/libllama.so | cut -d" " -f1)
B2=$(sha256sum $DST/build/bin/libllama.so | cut -d" " -f1)
if [ "$A1" = "$A2" ] && [ "$B1" = "$B2" ]; then
  echo "PHASE A: MATCH (object reuse + relink reproduces the landed engine byte for byte)"
else
  echo "PHASE A: DIFFER"
  echo "  llama-perplexity landed=$A1 ob1b=$A2"
  echo "  libllama.so      landed=$B1 ob1b=$B2"
  echo "  sizes:"; ls -l $SRC/build/bin/libllama.so $DST/build/bin/libllama.so
  echo "  --- does the binary embed its own source path? (the usual benign cause) ---"
  echo "  landed hits: $(strings $SRC/build/bin/libllama.so | grep -c "rs053/llama.cpp" || true)"
  echo "  ob1b   hits: $(strings $DST/build/bin/libllama.so | grep -c "ob1b/llama.cpp" || true)"
fi

echo "=== PHASE B: the one-line K=0 guard fix ==="
echo "--- before ---"
grep -n "OB1_K=%d out of range" $LEASE
# Exact literal replacement with a count assertion. Not sed: the line contains
# "||", and every convenient sed delimiter collides with something in it.
python3 - "$LEASE" <<'PYEOF'
import sys
p = sys.argv[1]
old = 'if (g_K <= 0 || g_K > g_E) ob1_fatal("OB1_K=%d out of range 1..%d", g_K, g_E);'
new = 'if (g_K <  0 || g_K > g_E) ob1_fatal("OB1_K=%d out of range 0..%d", g_K, g_E);'
s = open(p).read()
n = s.count(old)
if n != 1:
    sys.exit("GUARD EDIT ABORTED: expected exactly 1 occurrence, found %d" % n)
open(p, "w").write(s.replace(old, new))
print("guard edit applied: 1 occurrence replaced")
PYEOF
echo "--- after ---"
grep -n "OB1_K=%d out of range" $LEASE
echo "--- diff ---"
cd $DST && git diff --stat && git diff

nice -n 10 make -C $DST/build llama-perplexity -j4 2>&1 | tail -12
echo "--- phase B digests (the binary every OB-1b run uses) ---"
sha256sum $DST/build/bin/llama-perplexity $DST/build/bin/libllama.so
C2=$(sha256sum $DST/build/bin/libllama.so | cut -d" " -f1)
if [ "$B1" = "$C2" ]; then
  echo "PHASE B: libllama.so UNCHANGED after the edit -- the edit did not take, STOP"
else
  echo "PHASE B: libllama.so changed, as the one-line edit requires"
fi

echo "utc_end $(date -u +%Y-%m-%dT%H:%M:%SZ)"
echo "=== END OB1B BUILD ==="