diff --git a/inst/tinytest/test_flux_staging.R b/inst/tinytest/test_flux_staging.R index 6e7bbc0..192f082 100644 --- a/inst/tinytest/test_flux_staging.R +++ b/inst/tinytest/test_flux_staging.R @@ -47,12 +47,30 @@ expect_equal(diffuseR:::.pinned_set_gb("flux1", "bf16"), 34) # --- flux tier text_device: flux1 GPU-encodes only where T5 fits ------------------ # fp8/bf16 tiers (>=14 GB) onload T5; nf4 tiers keep CPU-fp32 encode. -expect_equal(recommend("flux1", vram_gb = 24)$text_device, "cuda") -expect_equal(recommend("flux1", vram_gb = 16)$text_device, "cuda") # fp8 tier -expect_equal(recommend("flux1", vram_gb = 10)$text_device, "cpu") # nf4 tier -expect_equal(recommend("flux1", vram_gb = 0)$text_device, "cpu") # cpu tier -# The small flux2/zimage encoder rides the GPU on every GPU tier. -expect_equal(recommend("flux2", vram_gb = 16)$text_device, "cuda") +# +# st_caps is pinned explicitly here. Left NULL, recommend() probes the +# *installed* safetensors, so the fp8 tier only exists on a machine whose +# build can read float8 -- which made this block pass on a dev box with +# the fork and fail on Windows R-devel, and would have failed on CRAN, +# where flux1 at 16 GB resolves to nf4 and its CPU encode instead. +st_fork <- list(bfloat16 = TRUE, float8_e4m3fn = TRUE) +st_cran <- list(bfloat16 = TRUE, float8_e4m3fn = FALSE) +expect_equal(recommend("flux1", vram_gb = 24, st_caps = st_fork)$text_device, + "cuda") +expect_equal(recommend("flux1", vram_gb = 16, st_caps = st_fork)$text_device, + "cuda") # fp8 tier +expect_equal(recommend("flux1", vram_gb = 16, st_caps = st_cran)$text_device, + "cpu") # same card, stock safetensors: nf4 tier +expect_equal(recommend("flux1", vram_gb = 10, st_caps = st_fork)$text_device, + "cpu") # nf4 tier +expect_equal(recommend("flux1", vram_gb = 0, st_caps = st_fork)$text_device, + "cpu") # cpu tier +# The small flux2/zimage encoder rides the GPU on every GPU tier, +# whichever safetensors is installed. +expect_equal(recommend("flux2", vram_gb = 16, st_caps = st_fork)$text_device, + "cuda") +expect_equal(recommend("flux2", vram_gb = 16, st_caps = st_cran)$text_device, + "cuda") # --- .flux_build_staging opt-out paths return NULL (no torch needed) -------------- diff --git a/inst/tinytest/test_fp8_ltx23.R b/inst/tinytest/test_fp8_ltx23.R index fb86506..936f275 100644 --- a/inst/tinytest/test_fp8_ltx23.R +++ b/inst/tinytest/test_fp8_ltx23.R @@ -8,14 +8,9 @@ if (!requireNamespace("safetensors", quietly = TRUE)) { exit_file("safetensors not installed") } # fp8 needs the F8-capable safetensors build -f8_ok <- tryCatch({ - x <- torch::torch_randn(2, 2)$to(dtype = torch::torch_float8_e4m3fn()) - tmp <- tempfile(fileext = ".safetensors") - safetensors::safe_save_file(list(w = x), tmp) - y <- safetensors::safe_load_file(tmp, framework = "torch") - unlink(tmp) - TRUE -}, error = function(e) FALSE) +# Same gate the quantizer uses, so the diffuseR.st_caps override +# reaches this guard too; a private probe would disagree with it. +f8_ok <- diffuseR:::.st_can_write("float8_e4m3fn") if (!f8_ok) exit_file("safetensors build lacks F8 support") library(diffuseR) diff --git a/inst/tinytest/test_quantize_flux.R b/inst/tinytest/test_quantize_flux.R index 03b8e02..32fe6a2 100644 --- a/inst/tinytest/test_quantize_flux.R +++ b/inst/tinytest/test_quantize_flux.R @@ -87,14 +87,11 @@ ltx23_release_dequant_buffers() # --- fp8 round trip (needs an F8-capable safetensors build) --------------------------- -f8_ok <- tryCatch({ - x <- torch::torch_randn(2, 2)$to(dtype = torch::torch_float8_e4m3fn()) - tmp <- tempfile(fileext = ".safetensors") - safetensors::safe_save_file(list(w = x), tmp) - y <- safetensors::safe_load_file(tmp, framework = "torch") - unlink(tmp) - TRUE -}, error = function(e) FALSE) +# Ask the same gate flux_quantize() asks, rather than re-probing here: a +# private probe can disagree with .st_can_write() whenever the +# diffuseR.st_caps override is set, and then this block runs only to hit +# the hard error the override was meant to simulate. +f8_ok <- diffuseR:::.st_can_write("float8_e4m3fn") if (f8_ok) { fp8_dir <- file.path(tempdir(), "flux-tiny-fp8") diff --git a/inst/tinytest/test_quantize_flux2.R b/inst/tinytest/test_quantize_flux2.R index 162f7e9..1a3c52d 100644 --- a/inst/tinytest/test_quantize_flux2.R +++ b/inst/tinytest/test_quantize_flux2.R @@ -78,14 +78,9 @@ ltx23_release_dequant_buffers() # --- fp8 round trips (streamed and resident) ------------------------------------------ -f8_ok <- tryCatch({ - x <- torch::torch_randn(2, 2)$to(dtype = torch::torch_float8_e4m3fn()) - tmp <- tempfile(fileext = ".safetensors") - safetensors::safe_save_file(list(w = x), tmp) - y <- safetensors::safe_load_file(tmp, framework = "torch") - unlink(tmp) - TRUE -}, error = function(e) FALSE) +# Same gate the quantizer uses, so the diffuseR.st_caps override +# reaches this guard too; a private probe would disagree with it. +f8_ok <- diffuseR:::.st_can_write("float8_e4m3fn") if (f8_ok) { fp8_dir <- file.path(tempdir(), "flux2-tiny-fp8") diff --git a/inst/tinytest/test_quantize_zimage.R b/inst/tinytest/test_quantize_zimage.R index 75b96de..e47b102 100644 --- a/inst/tinytest/test_quantize_zimage.R +++ b/inst/tinytest/test_quantize_zimage.R @@ -76,14 +76,9 @@ ltx23_release_dequant_buffers() # --- fp8 round trips (streamed and resident) ------------------------------------------ -f8_ok <- tryCatch({ - x <- torch::torch_randn(2, 2)$to(dtype = torch::torch_float8_e4m3fn()) - tmp <- tempfile(fileext = ".safetensors") - safetensors::safe_save_file(list(w = x), tmp) - y <- safetensors::safe_load_file(tmp, framework = "torch") - unlink(tmp) - TRUE -}, error = function(e) FALSE) +# Same gate the quantizer uses, so the diffuseR.st_caps override +# reaches this guard too; a private probe would disagree with it. +f8_ok <- diffuseR:::.st_can_write("float8_e4m3fn") if (f8_ok) { fp8_dir <- file.path(tempdir(), "zimage-tiny-fp8")