| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| #include "ds4.h" |
| #include "ds4_gpu_mgpu.h" |
|
|
| #include <cuda_runtime.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <unistd.h> |
|
|
| #define CHECK(cond, msg) \ |
| do { \ |
| if (!(cond)) { \ |
| fprintf(stderr, "FAIL: %s (line %d)\n", (msg), __LINE__); \ |
| return 1; \ |
| } \ |
| } while (0) |
|
|
| static int read_file_to_buf(const char *path, char **out_buf, long *out_len) { |
| FILE *f = fopen(path, "rb"); |
| if (!f) return 1; |
| if (fseek(f, 0, SEEK_END) != 0) { fclose(f); return 1; } |
| long n = ftell(f); |
| if (n < 0) { fclose(f); return 1; } |
| if (fseek(f, 0, SEEK_SET) != 0) { fclose(f); return 1; } |
| char *buf = (char *)malloc((size_t)n + 1); |
| if (!buf) { fclose(f); return 1; } |
| size_t r = fread(buf, 1, (size_t)n, f); |
| fclose(f); |
| buf[r] = '\0'; |
| *out_buf = buf; |
| *out_len = (long)r; |
| return 0; |
| } |
|
|
| int main(void) { |
| int dev_count = 0; |
| (void)cudaGetDeviceCount(&dev_count); |
| fprintf(stderr, "test_engine_mgpu_refusal: %d CUDA devices visible\n", dev_count); |
| if (dev_count < 2) { |
| fprintf(stderr, " skipping (need >= 2 devices)\n"); |
| return 0; |
| } |
|
|
| const char *model_path = getenv("DS4_TEST_MODEL"); |
| if (!model_path || !model_path[0]) { |
| fprintf(stderr, "FAIL: DS4_TEST_MODEL not set\n"); |
| return 1; |
| } |
|
|
| |
| |
| const char *cap_path = "/tmp/ds4_mgpu_refusal_stderr.log"; |
| (void)unlink(cap_path); |
| fflush(stderr); |
| int saved_stderr = dup(fileno(stderr)); |
| CHECK(saved_stderr >= 0, "dup stderr"); |
| FILE *redir = freopen(cap_path, "w+", stderr); |
| CHECK(redir != NULL, "freopen stderr"); |
|
|
| |
| ds4_gpu_config cfg; |
| memset(&cfg, 0, sizeof(cfg)); |
| cfg.n_gpus = 2; |
| cfg.device_indices[0] = 0; |
| cfg.device_indices[1] = 1; |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| cfg.vram_bytes[0] = (size_t)8ull * 1024u * 1024u * 1024u; |
| cfg.vram_bytes[1] = (size_t)8ull * 1024u * 1024u * 1024u; |
| cfg.safety_margin_bytes = 0; |
|
|
| ds4_engine_options opt; |
| memset(&opt, 0, sizeof(opt)); |
| opt.model_path = model_path; |
| opt.backend = DS4_BACKEND_CUDA; |
| opt.n_threads = 1; |
| opt.warm_weights = false; |
| opt.quality = false; |
|
|
| ds4_engine *engine = NULL; |
| int rc = ds4_engine_create_with_gpu_config(&engine, &opt, &cfg); |
|
|
| |
| fflush(stderr); |
| FILE *sink = freopen("/dev/null", "w", stderr); |
| CHECK(sink != NULL, "freopen stderr sink"); |
| int err_fd = fileno(stderr); |
| if (err_fd >= 0) { |
| (void)dup2(saved_stderr, err_fd); |
| (void)close(saved_stderr); |
| } |
|
|
| fprintf(stderr, " engine_create_with_gpu_config -> rc=%d, engine=%p\n", |
| rc, (void *)engine); |
|
|
| |
| char *cap = NULL; long cap_len = 0; |
| int read_rc = read_file_to_buf(cap_path, &cap, &cap_len); |
| if (read_rc != 0) { |
| fprintf(stderr, "FAIL: could not read captured stderr %s\n", cap_path); |
| return 1; |
| } |
| fprintf(stderr, " captured stderr (%ld bytes):\n----\n%s\n----\n", |
| cap_len, cap); |
|
|
| CHECK(rc != 0, "engine_create should refuse multi-tier and return nonzero"); |
| CHECK(engine == NULL, "engine pointer should be NULL on refusal"); |
| CHECK(strstr(cap, "multi-GPU layout") != NULL, |
| "stderr must contain 'multi-GPU layout' (init_multi must have succeeded " |
| "and layout must have been printed before refusal)"); |
| CHECK(strstr(cap, "mgpu-graph-session-cpu-spill") != NULL, |
| "stderr must name the wave-3b CPU-spill follow-up task"); |
| CHECK(strstr(cap, "CPU-spill placement detected") != NULL, |
| "stderr must contain the CPU-spill diagnostic line"); |
|
|
| free(cap); |
| (void)unlink(cap_path); |
| fprintf(stderr, "test_engine_mgpu_refusal PASS\n"); |
| return 0; |
| } |
|
|