Commit 9a1d03c7c for llama.cpp

commit 9a1d03c7ca2ca279feca8afd29d40c8e0fff9b6d
Author: Georgi Gerganov <ggerganov@gmail.com>
Date:   Fri Nov 6 14:52:26 2026 +0200

    tests : override hardware_concurrency in CI (#31797)

    The self-hosted CPU runners are containers with 8 CPUs, but
    std::thread::hardware_concurrency reports the cores of the host. The
    table mode of test-llama-context sizes its pool from that count, so it
    runs 4 models x 8 threads on an 8-CPU job and hangs.

    Add TEST_ARG_HARDWARE_CONCURRENCY and TEST_ARG_PARALLEL_WORKERS as the
    defaults for the auto-selected counts of test-llama-context and of
    test-backend-ops, and set them to 8 and 4 for cpu-x64-high-perf.

    Assisted-by: dsh:llama.cpp/ggml-org/Qwen3.8-Flash-Next-GGUF (RTX 5090 32GB, DDR5 128GB)

diff --git a/.github/workflows/ci-self-hosted-cpu.yml b/.github/workflows/ci-self-hosted-cpu.yml
index 4cb9be587..c03acdaa0 100644
--- a/.github/workflows/ci-self-hosted-cpu.yml
+++ b/.github/workflows/ci-self-hosted-cpu.yml
@@ -48,6 +48,12 @@ jobs:
   cpu-x64-high-perf:
     runs-on: hf-jobs-cpu-upgrade:ubuntu26_04

+    # note: this runner has 8 CPUs, but std::thread::hardware_concurrency reports the cores of the
+    #   host (https://github.com/ggml-org/llama.cpp/pull/31439#issuecomment-6683386059)
+    env:
+      TEST_ARG_HARDWARE_CONCURRENCY: 8
+      TEST_ARG_PARALLEL_WORKERS: 4
+
     steps:
       - name: Clone
         id: checkout
diff --git a/tests/test-backend-ops.cpp b/tests/test-backend-ops.cpp
index e35806f31..96954a5d7 100644
--- a/tests/test-backend-ops.cpp
+++ b/tests/test-backend-ops.cpp
@@ -48,9 +48,33 @@
 #ifdef __EMSCRIPTEN__
 #   define N_THREADS 1
 #else
-#   define N_THREADS std::thread::hardware_concurrency()
+static unsigned test_hardware_concurrency() {
+    const char * env = std::getenv("TEST_ARG_HARDWARE_CONCURRENCY");
+    if (env != nullptr) {
+        const long n = std::strtol(env, nullptr, 10);
+        if (n > 0) {
+            return (unsigned) n;
+        }
+    }
+
+    return std::thread::hardware_concurrency();
+}
+
+#   define N_THREADS test_hardware_concurrency()
 #endif

+static int test_parallel_workers(int default_workers) {
+    const char * env = std::getenv("TEST_ARG_PARALLEL_WORKERS");
+    if (env != nullptr) {
+        const long n = std::strtol(env, nullptr, 10);
+        if (n > 0) {
+            return (int) n;
+        }
+    }
+
+    return default_workers;
+}
+
 static void init_tensor_uniform(ggml_tensor * tensor, float min = -1.0f, float max = 1.0f) {
     if (ggml_is_empty(tensor)) {
         return;
@@ -14048,7 +14072,7 @@ int main(int argc, char ** argv) {
     const char * backend_filter = nullptr;
     const char * params_filter = nullptr;
     const char * test_file_path = nullptr;
-    int parallel_workers = 1;
+    int parallel_workers = test_parallel_workers(1);

     for (int i = 1; i < argc; i++) {
         if (strcmp(argv[i], "test") == 0) {
diff --git a/tests/test-llama-context.cpp b/tests/test-llama-context.cpp
index 0e905a7c7..62fedea50 100644
--- a/tests/test-llama-context.cpp
+++ b/tests/test-llama-context.cpp
@@ -16,6 +16,7 @@
 #include <atomic>
 #include <clocale>
 #include <cstdio>
+#include <cstdlib>
 #include <cstring>
 #include <filesystem>
 #include <mutex>
@@ -202,6 +203,30 @@ static void print_cases() {
     printf("\nthe [rs] cases are also run against a cache pre-filled with a known pattern\n\n");
 }

+static unsigned test_hardware_concurrency() {
+    const char * env = std::getenv("TEST_ARG_HARDWARE_CONCURRENCY");
+    if (env != nullptr) {
+        const long n = std::strtol(env, nullptr, 10);
+        if (n > 0) {
+            return (unsigned) n;
+        }
+    }
+
+    return std::thread::hardware_concurrency();
+}
+
+static int test_parallel_workers(int default_workers) {
+    const char * env = std::getenv("TEST_ARG_PARALLEL_WORKERS");
+    if (env != nullptr) {
+        const long n = std::strtol(env, nullptr, 10);
+        if (n > 0) {
+            return (int) n;
+        }
+    }
+
+    return default_workers;
+}
+
 int main(int argc, char ** argv) {
     std::setlocale(LC_NUMERIC, "C");

@@ -220,7 +245,7 @@ int main(int argc, char ** argv) {
     bool list_cases        = false;
     bool dump_logs_on_fail = true;

-    int parallel_workers = 0; // 0 = auto, same flag as in test-backend-ops
+    int parallel_workers = test_parallel_workers(0);

     auto parse_parallel_workers = [&](const char * flag, const char * value) {
         try {
@@ -401,7 +426,7 @@ int main(int argc, char ** argv) {
         return 1;
     }

-    const unsigned n_hw_2 = std::thread::hardware_concurrency() / 2;
+    const unsigned n_hw_2 = test_hardware_concurrency() / 2;
     const size_t   n_auto = std::max<size_t>(1, std::min<size_t>(n_hw_2, 4));
     const size_t   n_pool = parallel_workers > 0
         ? std::min<size_t>((size_t) parallel_workers, models.size())