From f342d7664d494440cd293c9c56e73c1a0ebd4e30 Mon Sep 17 00:00:00 2001 From: moonshadow-25 Date: Sat, 14 Mar 2026 12:36:37 +0800 Subject: [PATCH] [Windows/HIP] Fix APU large BAR detection to enable >64GB unified memory allocation Problem: On Windows, HIP unconditionally disables large BAR (largeBar_ = false) for all APU devices, regardless of their actual memory architecture. This causes unified memory architecture (UMA) APUs like AMD Strix Halo (gfx1151) to be artificially limited to ~64GB memory allocation, even when the system has 128GB+ RAM. Root cause: The premature redirect to RemoteUSWC heap in palmemory.cpp triggers the Windows GART allocator's 50%-of-RAM limit, preventing applications from utilizing the full unified memory capacity. Solution: 1. paldevice.cpp: Remove HIP-specific hardcoded largeBar_ = false. Instead, detect UMA APUs by checking if GpuHeapInvisible (discrete VRAM) is absent. On UMA systems, the entire system memory is GPU-local, so resizable BAR semantics naturally apply. 2. palmemory.cpp: For large-bar APUs, skip the early redirect to RemoteUSWC. Let the natural retry loop handle heap selection (Local -> Persistent -> RemoteUSWC), avoiding the Windows GART 50% cap. Testing: Tested on AMD Strix Halo (gfx1151) with 128GB RAM: - hipMallocManaged(64GB): Before: OOM, After: Success - hipMallocManaged(70GB): Before: OOM, After: Success - hipMallocManaged(80GB): Before: OOM, After: Success - Cumulative 2x40GB: Before: OOM, After: Success Impact: - Discrete GPUs: No change (invisible heap exists, largeBar_ determined by HW) - Non-large-bar APUs: Behavior unchanged (early redirect still applies) - Large-bar APUs: Now correctly utilize full unified memory - OpenCL: Benefits from the same fix (UMA detection is API-agnostic) This fix is critical for enabling large model inference on APU-based systems. Co-Authored-By: Claude Sonnet 4.6 --- projects/clr/rocclr/device/pal/paldevice.cpp | 7 ++++--- projects/clr/rocclr/device/pal/palmemory.cpp | 5 ++++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/projects/clr/rocclr/device/pal/paldevice.cpp b/projects/clr/rocclr/device/pal/paldevice.cpp index 92fac424324..f5554beb8ad 100644 --- a/projects/clr/rocclr/device/pal/paldevice.cpp +++ b/projects/clr/rocclr/device/pal/paldevice.cpp @@ -615,9 +615,10 @@ void NullDevice::fillDeviceInfo(const Pal::DeviceProperties& palProp, info_.aqlBarrierValue_ = true; #if defined(_WIN64) - if (amd::IS_HIP) { - info_.largeBar_ = false; - } else if (heaps[Pal::GpuHeapInvisible].logicalSize == 0) { + // For APU/integrated devices (no invisible/private VRAM heap), treat as large bar. + // This applies to both HIP and OpenCL: on UMA systems the entire system memory is + // GPU-local, so resizable BAR semantics apply. + if (heaps[Pal::GpuHeapInvisible].logicalSize == 0) { info_.largeBar_ = true; ClPrint(amd::LOG_INFO, amd::LOG_INIT, "Resizable bar enabled"); } diff --git a/projects/clr/rocclr/device/pal/palmemory.cpp b/projects/clr/rocclr/device/pal/palmemory.cpp index 329a1520cb0..60a4a4c05a8 100644 --- a/projects/clr/rocclr/device/pal/palmemory.cpp +++ b/projects/clr/rocclr/device/pal/palmemory.cpp @@ -116,7 +116,10 @@ bool Memory::create(Resource::MemoryType memType, Resource::CreateParams* params memType = Persistent; } - if (amd::IS_HIP && dev().settings().apuSystem_) { + if (amd::IS_HIP && dev().settings().apuSystem_ && !dev().info().largeBar_) { + // For large-bar APU (UMA, no invisible heap), skip the premature redirect to + // RemoteUSWC: the retry loop below will naturally fall through Local -> + // Persistent -> RemoteUSWC, avoiding the Windows GART 50%-of-RAM cap. Pal::gpusize totalAlloc = dev().TotalAlloc(); if (memType == Local && totalAlloc > dev().GetMaxFrameBuffer()) { memType = RemoteUSWC;