fetch_runtime.sh 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. #!/usr/bin/env bash
  2. # Fetch the third-party sources of the TP4 images at their pinned commits, verify every
  3. # download against runtime/sources.manifest, and apply this repository's patches.
  4. #
  5. # scripts/fetch_runtime.sh OUT_DIR [sglang-canary] [b12x] [b12x-next] (default: all three)
  6. #
  7. # OUT_DIR/sglang-canary/python SGLang dsv4.1 branch python/ tree (unpatched; the Dockerfile
  8. # applies runtime/sglang-rocenante.patch + runtime/roce_tp4_adapt.py)
  9. # OUT_DIR/b12x/{b12x,LICENSE} SG17 b12x (b12x.comm.roce) + b12x.comm.roce_ring
  10. # OUT_DIR/b12x_next/{b12x_next,LICENSE}
  11. # b12x main renamed to the package b12x_next, patched
  12. #
  13. # The Dockerfiles run this in their `fetch` stage. On a host it needs bash, curl, tar, perl,
  14. # patch and sha256sum (or shasum). Nothing is trusted without its sha256.
  15. set -euo pipefail
  16. ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
  17. MANIFEST="${MANIFEST:-$ROOT/runtime/sources.manifest}"
  18. OUT="${1:?usage: scripts/fetch_runtime.sh OUT_DIR [sglang-canary] [b12x] [b12x-next]}"
  19. shift
  20. COMPONENTS=("$@")
  21. [[ ${#COMPONENTS[@]} -gt 0 ]] || COMPONENTS=(sglang-canary b12x b12x-next)
  22. die() { echo "fetch_runtime: $*" >&2; exit 1; }
  23. if command -v sha256sum >/dev/null; then sha256() { sha256sum "$1" | cut -d' ' -f1; }
  24. else sha256() { shasum -a 256 "$1" | cut -d' ' -f1; }; fi
  25. # manifest row for a component id: "commit sha256 url"
  26. row() {
  27. local line
  28. line=$(awk -v id="$1" '$1 == id { print $2, $3, $4; n++ } END { exit n != 1 }' "$MANIFEST") \
  29. || die "manifest must have exactly one row for $1"
  30. printf '%s\n' "$line"
  31. }
  32. # fetch ID DEST: download the manifest url for ID to DEST and check its sha256
  33. fetch() {
  34. local id="$1" dest="$2" commit sum url got
  35. read -r commit sum url <<<"$(row "$id")"
  36. [[ "$commit" =~ ^[0-9a-f]{40}$ && "$sum" =~ ^[0-9a-f]{64}$ ]] || die "$id: malformed manifest row"
  37. [[ "$url" == https://*"$commit"* ]] || die "$id: url does not name commit $commit"
  38. curl -fsSL --retry 3 --retry-delay 5 -m 900 -o "$dest" "$url" || die "$id: download failed ($url)"
  39. got=$(sha256 "$dest")
  40. [[ "$got" == "$sum" ]] || die "$id: sha256 $got, manifest says $sum"
  41. echo " $id @ ${commit:0:12} sha256 ok"
  42. }
  43. # local files used as patches/overrides must match the manifest too
  44. check_local() {
  45. local path="$1" want got
  46. want=$(awk -v p="$path" '$1 == "local" && $2 == p { print $3 }' "$MANIFEST")
  47. [[ -n "$want" ]] || die "manifest has no local row for $path"
  48. got=$(sha256 "$ROOT/$path")
  49. [[ "$got" == "$want" ]] || die "$path: sha256 $got, manifest says $want"
  50. }
  51. tmp=$(mktemp -d)
  52. trap 'rm -rf "$tmp"' EXIT
  53. mkdir -p "$OUT"
  54. OUT="$(cd "$OUT" && pwd)"
  55. fetch_sglang_canary() {
  56. echo "sglang-canary"
  57. fetch sglang-canary "$tmp/sglang.tgz"
  58. rm -rf "$OUT/sglang-canary"
  59. mkdir -p "$OUT/sglang-canary" "$tmp/sglang"
  60. tar -xzf "$tmp/sglang.tgz" -C "$tmp/sglang" --strip-components=1
  61. [[ -d "$tmp/sglang/python/sglang" ]] || die "sglang-canary: unexpected archive layout"
  62. mv "$tmp/sglang/python" "$OUT/sglang-canary/python"
  63. read -r commit _ <<<"$(row sglang-canary)"
  64. echo "$commit" > "$OUT/sglang-canary/REF"
  65. }
  66. fetch_b12x() {
  67. echo "b12x (SG17 + roce_ring)"
  68. fetch b12x-sg17 "$tmp/b12x-sg17.tgz"
  69. rm -rf "$OUT/b12x"
  70. mkdir -p "$OUT/b12x" "$tmp/sg17"
  71. tar -xzf "$tmp/b12x-sg17.tgz" -C "$tmp/sg17"
  72. [[ -d "$tmp/sg17/b12x/comm/roce" && -f "$tmp/sg17/LICENSE" ]] || die "b12x-sg17: unexpected archive layout"
  73. mv "$tmp/sg17/b12x" "$tmp/sg17/LICENSE" "$OUT/b12x/"
  74. # roce_ring: nine files, each pinned; sparkring stores some with CRLF line ends
  75. local ring="$tmp/ring/roce_ring" id f
  76. mkdir -p "$ring"
  77. while read -r id; do
  78. f="${id#roce-ring/}"
  79. fetch "$id" "$ring/$f"
  80. perl -pi -e 's/\r\n/\n/' "$ring/$f"
  81. done < <(awk '$1 ~ /^roce-ring\// { print $1 }' "$MANIFEST")
  82. [[ $(find "$ring" -type f | wc -l) -eq 9 ]] || die "roce-ring: expected 9 files"
  83. check_local scripts/roce_ring-sparkring-f16b5f4.patch
  84. (cd "$tmp/ring" && patch -p1 --forward --quiet < "$ROOT/scripts/roce_ring-sparkring-f16b5f4.patch") \
  85. || die "roce_ring patch did not apply"
  86. mv "$ring" "$OUT/b12x/b12x/comm/roce_ring"
  87. }
  88. fetch_b12x_next() {
  89. echo "b12x-next (b12x main as b12x_next)"
  90. fetch b12x-main "$tmp/b12x-main.tgz"
  91. local commit dst="$OUT/b12x_next" patch_file="$ROOT/scripts/b12x_next-compact-n64-m64.patch"
  92. read -r commit _ <<<"$(row b12x-main)"
  93. rm -rf "$dst"
  94. mkdir -p "$dst" "$tmp/main"
  95. tar -xzf "$tmp/b12x-main.tgz" -C "$tmp/main" --strip-components=1
  96. [[ -d "$tmp/main/b12x" && -f "$tmp/main/LICENSE" ]] || die "b12x-main: unexpected archive layout"
  97. cp -R "$tmp/main/b12x" "$dst/b12x_next"
  98. cp "$tmp/main/LICENSE" "$dst/LICENSE"
  99. find "$dst/b12x_next" -name __pycache__ -type d -prune -exec rm -rf {} +
  100. # Both b12x revisions live in one image (RoCEnante needs the SG17 one), so main is renamed:
  101. # every whole-word `b12x` identifier/string in .py/.c/.cpp/.h -> `b12x_next` (imports,
  102. # CompileJob "module:function" strings, torch.library namespaces, cache paths), and every
  103. # B12X_* knob -> B12X_NEXT_*, so compile/tuning caches and knobs stay separate.
  104. find "$dst/b12x_next" -type f \( -name '*.py' -o -name '*.c' -o -name '*.cpp' -o -name '*.h' \) -print0 \
  105. | xargs -0 perl -pi -e 's/\bb12x\b(?!-)/b12x_next/g; s/\bB12X_(?!NEXT_)/B12X_NEXT_/g'
  106. echo "$commit" > "$dst/b12x_next/SOURCE_COMMIT"
  107. # admit the M64 tile for compact-N64 (N=576, EP1) prefill capacities (b12x pins them to M16)
  108. check_local scripts/b12x_next-compact-n64-m64.patch
  109. (cd "$dst" && patch -p0 --forward --quiet < "$patch_file") || die "compact-n64-m64 patch did not apply"
  110. grep -q "_compact_n64_tiles" "$dst/b12x_next/moe/fused_moe/_tuning.py" || die "compact-n64-m64 patch did not apply"
  111. sha256 "$patch_file" | cut -c1-16 > "$dst/b12x_next/SOURCE_PATCH"
  112. # The measured images never carried sequence/engram (an op package unused by the MoE path;
  113. # a repository-wide `engram/` ignore rule kept it out). Left out so the build matches them.
  114. rm -rf "$dst/b12x_next/sequence/engram"
  115. local left
  116. left=$(find "$dst/b12x_next" -name '*.py' -print0 | xargs -0 perl -ne 'print "$ARGV\n" if /\bb12x\b(?!-)/ || /\bB12X_(?!NEXT_)/' | sort -u)
  117. [[ -z "$left" ]] || die "unrenamed b12x references in: $left"
  118. }
  119. for c in "${COMPONENTS[@]}"; do
  120. case "$c" in
  121. sglang-canary) fetch_sglang_canary ;;
  122. b12x) fetch_b12x ;;
  123. b12x-next) fetch_b12x_next ;;
  124. *) die "unknown component $c (sglang-canary, b12x, b12x-next)" ;;
  125. esac
  126. done
  127. check_local runtime/sglang-rocenante.patch
  128. check_local runtime/flash_mla_sm120.canary.py
  129. echo "fetched into $OUT: ${COMPONENTS[*]}"