From abfc45b9cb21eae4848cb82196e659f42c9a8341 Mon Sep 17 00:00:00 2001 From: danielhanchen Date: Mon, 31 Aug 2026 07:12:02 +0000 Subject: [PATCH] ggml-cuda: avoid direct ROCm_Host compute on HIP integrated GPUs Port of ggml-org#25863 at ce82541a, unmodified except for dropping that PR's file mode change. c7d87229 (ggml-org#24233) restored prop.integrated on HIP builds. CUDA keeps it off, with the comment 'Temporarily disabled due to issues with corrupted output'. With it on, the scheduler may place a compute input in pinned host memory, where an H2D input write can race a graph that is still running. Two reporters bisected to that commit independently, from different symptoms: ggml-org#25992 gets another slot's response verbatim under -np 4 --kv-unified, and ggml-org#27506 sees perplexity go from 7.72 to 3024 on Llama-3.2-3B. lemonade-sdk/lemonade#3160 is the same shape on our own Qwen3.8-27B GGUF. Scope, checked rather than assumed: info.devices[id].integrated is set from prop.integrated only under GGML_USE_HIP, and is hard false on CUDA and MUSA (ggml-cuda.cu:305-309), so the supports_buft change is dead code off HIP. Discrete AMD is unaffected because prop.integrated is false there. One hunk is broader: get_host_buffer_type now returns nullptr when GGML_CUDA_NO_PINNED is set, on every backend. That is a consistency fix, since props->host_buffer already reported false while the buffer type was still handed out. The only caller in the tree, ggml-backend-meta.cpp:379, handles nullptr. Pinned in scripts/unsloth/pr-set.json so the nightlies carry it; the pin comes out when a base tag contains the upstream merge. --- ggml/src/ggml-cuda/ggml-cuda.cu | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/ggml/src/ggml-cuda/ggml-cuda.cu b/ggml/src/ggml-cuda/ggml-cuda.cu index 2456f7dcc62..0ed65b5b9f1 100644 --- a/ggml/src/ggml-cuda/ggml-cuda.cu +++ b/ggml/src/ggml-cuda/ggml-cuda.cu @@ -4822,6 +4822,22 @@ static enum ggml_backend_dev_type ggml_backend_cuda_device_get_type(ggml_backend : GGML_BACKEND_DEVICE_TYPE_GPU; } +static bool ggml_backend_cuda_host_buffer_supported() { + return getenv("GGML_CUDA_NO_PINNED") == nullptr; +} + +static bool ggml_backend_cuda_device_supports_cuda_host_buft(int device) { +#if defined(GGML_USE_HIP) + if (ggml_cuda_info().devices[device].integrated) { + return false; + } +#else + GGML_UNUSED(device); +#endif + + return ggml_backend_cuda_host_buffer_supported(); +} + static void ggml_backend_cuda_device_get_props(ggml_backend_dev_t dev, ggml_backend_dev_props * props) { ggml_backend_cuda_device_context * ctx = (ggml_backend_cuda_device_context *)dev->context; @@ -4831,7 +4847,7 @@ static void ggml_backend_cuda_device_get_props(ggml_backend_dev_t dev, ggml_back props->device_id = ctx->pci_bus_id.empty() ? nullptr : ctx->pci_bus_id.c_str(); ggml_backend_cuda_device_get_memory(dev, &props->memory_free, &props->memory_total); - bool host_buffer = getenv("GGML_CUDA_NO_PINNED") == nullptr; + bool host_buffer = ggml_backend_cuda_host_buffer_supported(); #ifdef GGML_CUDA_NO_PEER_COPY bool events = false; #else @@ -4860,6 +4876,10 @@ static ggml_backend_buffer_type_t ggml_backend_cuda_device_get_buffer_type(ggml_ static ggml_backend_buffer_type_t ggml_backend_cuda_device_get_host_buffer_type(ggml_backend_dev_t dev) { GGML_UNUSED(dev); + if (!ggml_backend_cuda_host_buffer_supported()) { + return nullptr; + } + return ggml_backend_cuda_host_buffer_type(); } @@ -5320,7 +5340,10 @@ static bool ggml_backend_cuda_device_supports_op(ggml_backend_dev_t dev, const g static bool ggml_backend_cuda_device_supports_buft(ggml_backend_dev_t dev, ggml_backend_buffer_type_t buft) { ggml_backend_cuda_device_context * dev_ctx = (ggml_backend_cuda_device_context *) dev->context; const bool integrated = ggml_cuda_info().devices[dev_ctx->device].integrated; - return (ggml_backend_buft_is_cuda(buft) && buft->device == dev) || (integrated && ggml_backend_buft_is_cuda_host(buft)); + return (ggml_backend_buft_is_cuda(buft) && buft->device == dev) || + (integrated && + ggml_backend_buft_is_cuda_host(buft) && + ggml_backend_cuda_device_supports_cuda_host_buft(dev_ctx->device)); } static int64_t get_op_batch_size(const ggml_tensor * op) {