Commit 7021f7e09 for llama.cpp
commit 7021f7e0993c2bae3860a9b7e6507bead16c90af
Author: Joseph Patricio <122133686+JoeyPatricio@users.noreply.github.com>
Date: Wed Nov 11 22:50:32 2026 -0800
CUDA: add cuda debug buffer pool (#31919)
* CUDA: add cuda debug buffer pool
* CUDA: add code comment for debug pool with compute-sanitizer
diff --git a/ggml/src/ggml-cuda/common.cuh b/ggml/src/ggml-cuda/common.cuh
index 624e90e13..dfb222b4f 100644
--- a/ggml/src/ggml-cuda/common.cuh
+++ b/ggml/src/ggml-cuda/common.cuh
@@ -1271,6 +1271,8 @@ const ggml_cuda_device_info & ggml_cuda_info();
void ggml_cuda_set_device(int device);
int ggml_cuda_get_device();
+bool ggml_cuda_pool_debug_enabled();
+
struct ggml_cuda_pool {
virtual ~ggml_cuda_pool() = default;
diff --git a/ggml/src/ggml-cuda/ggml-cuda.cu b/ggml/src/ggml-cuda/ggml-cuda.cu
index aa51b72bf..92ae9848a 100644
--- a/ggml/src/ggml-cuda/ggml-cuda.cu
+++ b/ggml/src/ggml-cuda/ggml-cuda.cu
@@ -181,6 +181,11 @@ static bool ggml_cuda_p2p_enabled() {
return enabled;
}
+bool ggml_cuda_pool_debug_enabled() {
+ static const bool enabled = ggml_cuda_env_flag("GGML_CUDA_POOL_DEBUG");
+ return enabled;
+}
+
static int ggml_cuda_op_offload_min_batch() {
static const int min_batch = ggml_cuda_env_int("GGML_OP_OFFLOAD_MIN_BATCH", 32);
return min_batch;
@@ -736,9 +741,43 @@ struct ggml_cuda_pool_vmm : public ggml_cuda_pool {
};
#endif // defined(GGML_USE_VMM)
+// Debug pool for NVIDIA compute-sanitizer, e.g.
+// `GGML_CUDA_POOL_DEBUG=1 compute-sanitizer --tool memcheck ./build/bin/test-backend-ops -b CUDA0`
+// Allocations are exact-size and freed on release,
+// allowing memcheck to catch out-of-bounds and use-after-free.
+struct ggml_cuda_pool_debug : public ggml_cuda_pool {
+ int device;
+ size_t pool_size = 0; // leak check (error if not zero at destruction)
+
+ explicit ggml_cuda_pool_debug(int device) :
+ device(device) {
+ }
+
+ ~ggml_cuda_pool_debug() {
+ GGML_ASSERT(pool_size == 0);
+ }
+
+ void * alloc(size_t size, size_t * actual_size) override {
+ void * ptr;
+ CUDA_CHECK(ggml_cuda_device_malloc(&ptr, size, device));
+ *actual_size = size;
+ pool_size += size;
+ return ptr;
+ }
+
+ void free(void * ptr, size_t size) override {
+ ggml_cuda_set_device(device);
+ CUDA_CHECK(cudaFree(ptr));
+ pool_size -= size;
+ }
+};
+
std::unique_ptr<ggml_cuda_pool> ggml_backend_cuda_context::new_pool_for_device(ggml_backend_cuda_context & ctx,
int device,
[[maybe_unused]] int stream_no) {
+ if (ggml_cuda_pool_debug_enabled()) {
+ return std::unique_ptr<ggml_cuda_pool>(new ggml_cuda_pool_debug(device));
+ }
#if defined(GGML_USE_VMM)
if (ggml_cuda_info().devices[device].vmm) {
return std::unique_ptr<ggml_cuda_pool>(new ggml_cuda_pool_vmm(device));
diff --git a/ggml/src/ggml-cuda/graph.cuh b/ggml/src/ggml-cuda/graph.cuh
index c26373700..7b9c27789 100644
--- a/ggml/src/ggml-cuda/graph.cuh
+++ b/ggml/src/ggml-cuda/graph.cuh
@@ -64,7 +64,7 @@ struct ggml_cuda_graph {
bool is_enabled() const {
static const bool disable_cuda_graphs_due_to_env = (getenv("GGML_CUDA_DISABLE_GRAPHS") != nullptr);
- return !(disable_due_to_gpu_arch || disable_cuda_graphs_due_to_env);
+ return !(disable_due_to_gpu_arch || disable_cuda_graphs_due_to_env || ggml_cuda_pool_debug_enabled());
}
#endif
};