fix(CRITICAL): bridge build delayed binding + Docker tolerance + improved preload
build_unified_bridge.sh:
- set -euo → set -eo (avoid unbound var failures)
- Drop -ltorch_cuda -lc10_cuda (unavailable at Docker build time)
- Add -Wl,--unresolved-symbols=ignore-in-shared-libs
ixformer::infer symbols resolved at runtime via RTLD_GLOBAL preload
Dockerfile Step 6:
- Wrap in (... || echo non-fatal) so Docker build continues if bridge fails
ix_unified.py:
- 3-phase preload: lib*.so → _ixformer_torch*.so → remaining .so
- All loaded with ctypes.RTLD_GLOBAL so symbols visible to bridge
- Added /workspace and /home/dylan search paths
Verified on real machine: bridge compiles (272K), undefined symbols expected
until ixformer .so preloaded at runtime by ix_unified.py
This commit is contained in:
@@ -52,9 +52,10 @@ RUN chmod +x /workspace/qwen3_6_scripts/patch_ops.sh && \
|
||||
bash ./patch_ops.sh 2>&1 | tee /workspace/patch_ops.log ; \
|
||||
echo "[Dockerfile] patch_ops exit code: $?"
|
||||
|
||||
# Step 6: Build ix_unified_bridge.so (links against base image ixformer at runtime)
|
||||
# Step 6: Build ix_unified_bridge.so (ixformer::infer symbols resolved at runtime via RTLD_GLOBAL preload)
|
||||
# Tolerant: bridge is optional — corex_moe.py has ixformer.functions fallback
|
||||
RUN chmod +x /workspace/ex_engine/build_unified_bridge.sh && \
|
||||
bash /workspace/ex_engine/build_unified_bridge.sh 2>&1 | tee -a /workspace/ex_build.log ; \
|
||||
(bash /workspace/ex_engine/build_unified_bridge.sh 2>&1 || echo "[Dockerfile] bridge build FAILED (non-fatal)") | tee -a /workspace/ex_build.log ; \
|
||||
echo "[Dockerfile] ix_unified_bridge build exit code: $?"
|
||||
|
||||
# Step 7: Deploy ix_unified and ex_engine Python modules to vllm path
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env bash
|
||||
# build_unified_bridge.sh — Compile ix_unified_bridge.so on BI-V100
|
||||
# Uses manual compiler flags since torch.utils.cpp_extension is stripped from corex torch.
|
||||
set -euo pipefail
|
||||
set -eo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
SRC_DIR="${SCRIPT_DIR}/csrc/ilu"
|
||||
@@ -34,8 +34,9 @@ $CXX -shared -fPIC -O2 -std=c++17 \
|
||||
-I"$TORCH_INC" \
|
||||
-I"$TORCH_INC2" \
|
||||
-L"$TORCH_LIB" \
|
||||
-ltorch -ltorch_cpu -ltorch_cuda -lc10 -lc10_cuda \
|
||||
-ltorch -ltorch_cpu -lc10 \
|
||||
-Wl,--no-as-needed,-rpath,"$TORCH_LIB" \
|
||||
-Wl,--unresolved-symbols=ignore-in-shared-libs \
|
||||
-D_GLIBCXX_USE_CXX11_ABI=0 \
|
||||
-DTORCH_EXTENSION_NAME=ix_unified_bridge \
|
||||
"$SRC_DIR/ix_unified_bridge.cpp" \
|
||||
|
||||
@@ -30,12 +30,36 @@ def _load_bridge():
|
||||
if _bridge is not None:
|
||||
return _bridge
|
||||
|
||||
# Pre-load ixformer .so symbols (bridge links against them at runtime)
|
||||
# Pre-load ixformer .so symbols into GLOBAL symbol table.
|
||||
# ix_unified_bridge.so has undefined ixformer::infer::* symbols that get
|
||||
# resolved at runtime. Python default import uses RTLD_LOCAL, so we must
|
||||
# force RTLD_GLOBAL on the ixformer .so files BEFORE loading our bridge.
|
||||
try:
|
||||
import ctypes, glob as _glob
|
||||
|
||||
for _base in ["/usr/local/corex/lib64/python3/dist-packages/ixformer",
|
||||
"/usr/local/corex/lib/python3/dist-packages/ixformer"]:
|
||||
for _so in _glob.glob(os.path.join(_base, "**/*.so"), recursive=True):
|
||||
"/usr/local/corex/lib/python3/dist-packages/ixformer",
|
||||
"/usr/local/corex/lib64"]:
|
||||
if not os.path.isdir(_base):
|
||||
continue
|
||||
# Phase 1: lib*.so (libixformer.so, libixattn.so — dependencies first)
|
||||
for _so in sorted(_glob.glob(os.path.join(_base, "lib*.so*"))):
|
||||
try:
|
||||
ctypes.CDLL(_so, mode=ctypes.RTLD_GLOBAL)
|
||||
except Exception:
|
||||
pass
|
||||
# Phase 2: _ixformer_torch*.so (contains ixformer::infer::* symbols)
|
||||
for _so in sorted(_glob.glob(os.path.join(_base, "_ixformer_torch*.so"))):
|
||||
try:
|
||||
ctypes.CDLL(_so, mode=ctypes.RTLD_GLOBAL)
|
||||
logger.info("Preloaded ixformer: %s", _so)
|
||||
except Exception:
|
||||
pass
|
||||
# Phase 3: any remaining .so in subdirs
|
||||
for _so in sorted(_glob.glob(os.path.join(_base, "**/*.so"), recursive=True)):
|
||||
bn = os.path.basename(_so)
|
||||
if bn.startswith("lib") or "_ixformer" in bn:
|
||||
continue
|
||||
try:
|
||||
ctypes.CDLL(_so, mode=ctypes.RTLD_GLOBAL)
|
||||
except Exception:
|
||||
@@ -50,6 +74,10 @@ def _load_bridge():
|
||||
search_paths.append(os.path.join(here, "..", "build"))
|
||||
search_paths.append(here)
|
||||
|
||||
# 2. Workspace build dirs (Docker / real machine)
|
||||
search_paths.append("/workspace/ex_engine/build")
|
||||
search_paths.append("/home/dylan/project_6/ex_engine/build")
|
||||
|
||||
# 2. vllm install root (where prebuilt .so are deployed)
|
||||
for p in sys.path:
|
||||
if "vllm" in p or "dist-packages" in p:
|
||||
|
||||
Reference in New Issue
Block a user