Studio: gate ROCm hosts out of CPU prebuilt and require offload signal in smoke-test
- direct_upstream_release_plan: Linux x86_64 and arm64 CPU branches now also require not host.has_rocm, so a ROCm host whose HIP prebuilt is missing or rejected never silently takes a CPU upstream tarball as a 'success'. - setup.ps1: a Windows ROCm host with no usable HIP prebuilt and no HIP source build path is now marked LlamaCppDegraded so the CPU last-resort installs a clearly labelled CPU build instead of a 'built' install that runs on CPU. - validate_server gains require_gpu_signal; smoke_test_server_binary sets it for GPU install kinds so the '0 = offload confirmed' CLI contract treats a no-GPU-signal log as inconclusive (EXIT_ERROR) rather than a silent pass. - run_smoke_spoof + unit test cover the new no-signal-is-inconclusive contract.
This commit is contained in:
parent
100e27ffe7
commit
889e889d9c
4 changed files with 58 additions and 8 deletions
|
|
@ -1611,7 +1611,12 @@ def direct_upstream_release_plan(
|
|||
install_kind = "macos-x64",
|
||||
)
|
||||
)
|
||||
elif host.is_linux and host.is_x86_64 and not host.has_usable_nvidia:
|
||||
elif (
|
||||
host.is_linux
|
||||
and host.is_x86_64
|
||||
and not host.has_usable_nvidia
|
||||
and not host.has_rocm
|
||||
):
|
||||
asset_name = f"llama-{release_tag}-bin-ubuntu-x64.tar.gz"
|
||||
asset_url = assets.get(asset_name)
|
||||
if asset_url:
|
||||
|
|
@ -1625,7 +1630,12 @@ def direct_upstream_release_plan(
|
|||
install_kind = "linux-cpu",
|
||||
)
|
||||
)
|
||||
elif host.is_linux and host.is_arm64 and not host.has_usable_nvidia:
|
||||
elif (
|
||||
host.is_linux
|
||||
and host.is_arm64
|
||||
and not host.has_usable_nvidia
|
||||
and not host.has_rocm
|
||||
):
|
||||
# Upstream ggml-org/llama.cpp ships llama-bNNNN-bin-ubuntu-arm64.tar.gz
|
||||
# (visible in the b9334 release manifest). Without this branch the
|
||||
# selector returned 0 attempts and the installer fell back to a
|
||||
|
|
@ -5766,6 +5776,7 @@ def validate_server(
|
|||
*,
|
||||
runtime_line: str | None = None,
|
||||
install_kind: str | None = None,
|
||||
require_gpu_signal: bool = False,
|
||||
) -> None:
|
||||
last_failure: PrebuiltFallback | None = None
|
||||
for port_attempt in range(1, SERVER_PORT_BIND_ATTEMPTS + 1):
|
||||
|
|
@ -5908,10 +5919,10 @@ def validate_server(
|
|||
# the next bundle / source build instead of stopping here.
|
||||
if _enable_gpu_layers:
|
||||
log_handle.flush()
|
||||
if (
|
||||
server_log_shows_gpu_offload(read_full_log(log_path))
|
||||
is False
|
||||
):
|
||||
offload = server_log_shows_gpu_offload(
|
||||
read_full_log(log_path)
|
||||
)
|
||||
if offload is False:
|
||||
raise GpuOffloadFailure(
|
||||
"llama-server served a completion but loaded the "
|
||||
"model entirely on CPU despite GPU offload being "
|
||||
|
|
@ -5924,6 +5935,17 @@ def validate_server(
|
|||
"(unslothai/unsloth#5807, #5106):\n"
|
||||
+ read_log_excerpt(log_path)
|
||||
)
|
||||
# No GPU signal: install validation stays conservative
|
||||
# (never reject on no evidence), but --smoke-test sets
|
||||
# require_gpu_signal so its "0 = offload confirmed"
|
||||
# contract does not pass an unproven log.
|
||||
if offload is None and require_gpu_signal:
|
||||
raise PrebuiltFallback(
|
||||
"llama-server served a completion but its startup "
|
||||
"log carried no GPU-offload signal; smoke-test "
|
||||
"result is inconclusive:\n"
|
||||
+ read_log_excerpt(log_path)
|
||||
)
|
||||
return
|
||||
finally:
|
||||
if process is not None and process.poll() is None:
|
||||
|
|
@ -6925,6 +6947,9 @@ def smoke_test_server_binary(
|
|||
Path(install_dir).expanduser().resolve() if install_dir else server_path.parent
|
||||
)
|
||||
resolved_kind = install_kind or resolve_smoke_test_install_kind(host)
|
||||
# For a GPU kind, the CLI contract is "0 = offload confirmed", so an
|
||||
# inconclusive (no-signal) log must not pass -- require a positive signal.
|
||||
require_signal = resolved_kind in _GPU_INSTALL_KINDS
|
||||
if probe:
|
||||
probe_path = Path(probe).expanduser().resolve()
|
||||
if not probe_path.exists():
|
||||
|
|
@ -6935,6 +6960,7 @@ def smoke_test_server_binary(
|
|||
host,
|
||||
resolved_install_dir,
|
||||
install_kind = resolved_kind,
|
||||
require_gpu_signal = require_signal,
|
||||
)
|
||||
else:
|
||||
with tempfile.TemporaryDirectory(prefix = "unsloth-llama-smoke-") as tmp:
|
||||
|
|
@ -6948,6 +6974,7 @@ def smoke_test_server_binary(
|
|||
host,
|
||||
resolved_install_dir,
|
||||
install_kind = resolved_kind,
|
||||
require_gpu_signal = require_signal,
|
||||
)
|
||||
return resolved_kind
|
||||
|
||||
|
|
|
|||
|
|
@ -2667,6 +2667,14 @@ if (-not $NeedLlamaSourceBuild) {
|
|||
substep "GGUF inference and export will not be available." "Yellow"
|
||||
substep "Install CMake from https://cmake.org/download/ and re-run setup." "Yellow"
|
||||
$script:LlamaCppDegraded = $true
|
||||
} elseif ($HasROCm -and -not $HasNvidiaSmi) {
|
||||
# Windows has no HIP source-build path, so a ROCm host whose HIP prebuilt was
|
||||
# missing or rejected must not silently CPU-source-build. Mark degraded so
|
||||
# the CPU-prebuilt last resort below installs a clearly labelled CPU build
|
||||
# instead of a "built" install that runs on CPU (#5807).
|
||||
Write-Host ""
|
||||
step "llama.cpp" "no usable HIP prebuilt and no Windows HIP source build; using CPU prebuilt" "Yellow"
|
||||
$script:LlamaCppDegraded = $true
|
||||
} else {
|
||||
# A source build is committed here. The CUDA toolkit is only needed now, so
|
||||
# resolve (and winget-install if needed) it lazily, failing fast if no
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ def main() -> int:
|
|||
("cuda", GPU_KIND, 0, "GPU binary tagged GPU is accepted"),
|
||||
("cuda_buffer", GPU_KIND, 0, "GPU buffer-format binary is accepted"),
|
||||
("cpu", CPU_KIND, 0, "CPU binary tagged CPU is not gated"),
|
||||
("no_signal", GPU_KIND, 0, "no-signal log is not rejected"),
|
||||
("no_signal", GPU_KIND, 1, "no-signal GPU log is inconclusive (exit 1)"),
|
||||
]
|
||||
for mode, kind, expected, label in cases:
|
||||
rc = run_smoke(wrapper, probe, kind, mode)
|
||||
|
|
|
|||
|
|
@ -408,11 +408,26 @@ def test_cpu_kind_not_gpu_gated(patched_server, tmp_path):
|
|||
|
||||
|
||||
def test_gpu_intent_no_signal_accepted(patched_server, tmp_path):
|
||||
# No buffer/device signal -> conservative: do not reject on no evidence.
|
||||
# No buffer/device signal -> conservative: do not reject on no evidence
|
||||
# (plain install validation; require_gpu_signal defaults False).
|
||||
patched_server(NO_SIGNAL_LOG)
|
||||
_run_validate(tmp_path, nvidia_host(), "linux-cuda") # no raise
|
||||
|
||||
|
||||
def test_smoke_test_no_signal_gpu_is_inconclusive(patched_server, tmp_path):
|
||||
# The smoke-test CLI sets require_gpu_signal, so a no-signal GPU log is
|
||||
# inconclusive (PrebuiltFallback -> EXIT_ERROR), not a silent pass.
|
||||
patched_server(NO_SIGNAL_LOG)
|
||||
server = tmp_path / "llama-server"
|
||||
server.write_text("#!/bin/sh\n")
|
||||
probe = tmp_path / "probe.gguf"
|
||||
probe.write_bytes(b"GGUF")
|
||||
with pytest.raises(PrebuiltFallback):
|
||||
smoke_test_server_binary(
|
||||
str(server), nvidia_host(), install_dir = str(tmp_path), probe = str(probe)
|
||||
)
|
||||
|
||||
|
||||
def test_rocm_cpu_only_rejected(patched_server, tmp_path):
|
||||
patched_server(CPU_ONLY_DEVICE_INFO_LOG)
|
||||
with pytest.raises(PrebuiltFallback):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue