From 043f806207303586a0c903f7c1aaa208be03af97 Mon Sep 17 00:00:00 2001 From: danielhanchen Date: Sun, 30 Aug 2026 11:11:20 +0000 Subject: [PATCH] ggml-cuda: stop scheduling compute onto the host buffer on HIP integrated GPUs Carries ggml-org/llama.cpp#25863. On HIP the device info sets integrated = prop.integrated, while the CUDA branch of the same #if keeps it false 'due to issues with corrupted output'. That asymmetry re-enables direct host-buffer compute on APUs, which is the path the gfx1151 corruption reports bisect to. Pinned staging stays available; only compute directly out of the host buffer is refused. --- ggml/src/ggml-cuda/ggml-cuda.cu | 35 +++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/ggml/src/ggml-cuda/ggml-cuda.cu b/ggml/src/ggml-cuda/ggml-cuda.cu index 2456f7dcc62..a7db96af999 100644 --- a/ggml/src/ggml-cuda/ggml-cuda.cu +++ b/ggml/src/ggml-cuda/ggml-cuda.cu @@ -4822,6 +4822,30 @@ 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; +} + +// Whether the scheduler may place a COMPUTE input on the pinned host buffer type. +// +// On HIP the device info sets `integrated = prop.integrated`, while the CUDA +// branch of the same #if keeps it false "due to issues with corrupted output". +// That asymmetry is what re-enabled direct host-buffer compute on APUs, and it +// is the path several gfx1151 corruption reports bisect to. Staging through +// pinned host memory stays available; only compute directly out of it is +// refused, which is the narrowest change that closes the reports. +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 +4855,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 +4884,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 +5348,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) {