VK_EXT_memory_budget ile Vulkan'da GPU bellek bütçesi ve canlı heap kullanımını sorgulama

Example: VulkanExamples/p42_budget

Serideki post 42 (post 28: capability sorguları, post: bellek tipleri).

VkPhysicalDeviceMemoryProperties size heap boyutlarını söyler — kutunun üstünde yazan 16GB. Söylemediği: o heap’in ne kadarının zaten gittiği (diğer uygulamalar, compositor, kendi önceki allocation’larınız) veya driver’ın size ne kadar vermeye istekli olduğu. VK_EXT_memory_budget tek bir zincirlenmiş struct ile iki boşluğu da kapatır:

main.cpp (excerpt)
vk::PhysicalDeviceMemoryBudgetPropertiesEXT budget{};
vk::PhysicalDeviceMemoryProperties2 mp{};
mp.pNext = &budget;
phys.getMemoryProperties2(&mp);

for (uint32_t i = 0; i < mp.memoryProperties.memoryHeapCount; ++i)
    printf("heap%u size=%lluMB usage=%lluMB budget=%lluMB\n", i,
           (unsigned long long)(mp.memoryProperties
                                    .memoryHeaps[i].size >> 20),
           (unsigned long long)(budget.heapUsage[i] >> 20),
           (unsigned long long)(budget.heapBudget[i] >> 20));
  • heapBudget[i] — driver’ın şu an allocate etmenize izin verdiği (heap boyutu − driver rezervasyonları − diğer süreçler).
  • heapUsage[i] — şu an gerçekten allocate edilmiş olan.

Test Radeon’unda:

example.sh
--- before allocations ---
heap0 size=16128MB usage=0MB budget=15124MB flags=0x1   # VRAM
heap1 size=15540MB usage=0MB budget=15339MB flags=0x0   # GTT/host
heap2 size=256MB   usage=0MB budget=54MB   flags=0x1    # BAR carve-out
--- after 3x256MB device-local ---
heap0 size=16128MB usage=768MB budget=15124MB flags=0x1

İki öğretici ayrıntı:

  • budget ≠ size: heap0’ın 16GB’ı 15.1GB bütçe gösterir — driver ~1GB’ı kendine ayırır (page table’lar, firmware, diğer istemciler). heap2 resizable-BAR penceresidir: 256MB heap ama yalnızca 54MB bütçe, yani çoğu kalıcı olarak rezerve.
  • usage sizden fazlasını sayar: heapUsage paylaşılan heap’lerde sistem çapındadır — VRAM allocate eden başka bir uygulama burada görünür; bir uygulamanın heap boyutuna güvenmek yerine cache tahliye ederken veya büyütürken bütçeyi yeniden kontrol etmesi gerekmesinin tam nedeni budur.

Kontrol

check.py
# SPDX-License-Identifier: CC0-1.0
import re, subprocess

o = subprocess.run(["./app"], check=True, capture_output=True,
                   text=True).stdout

def parse(text):
    return {i: (int(u), int(b)) for i, u, b in re.findall(
        r"heap(\d+) size=\d+MB usage=(\d+)MB budget=(\d+)MB "
        r"flags=0x1", text)}

before, _, after = o.partition("--- after 3x256MB device-local ---")
heaps_b = parse(before)
heaps_a = parse(after)
assert heaps_b and heaps_a, o
grew = [i for i in heaps_a
        if heaps_a[i][0] - heaps_b.get(i, (0, 0))[0] >= 700]
assert grew, f"no heap grew by ~768MB: {o}"
print("OK: heap budget/usage reported, device-local usage +768MB")
example.sh
$ python3 check.py
OK: heap budget/usage reported, device-local usage +768MB

Nasıl KULLANILMAMALI

  • Bütçeyi söz olarak görmeyin — sorgu ile vkAllocateMemoryınız arasında küçülebilir (başka bir uygulama belleği kaptı). Yine de eOutOfDeviceMemory‘yi ele alın; bütçe bir politika girdisidir, rezervasyon değil.
  • Bütçeleri toplamayın — heap’ler garip şekillerde çakışır (BAR heap’i VRAM’e bir penceredir); flag’leriyle doğru heap’i seçin.
  • Her frame’de yeniden sorgulamayın — bu syscall’e yakın bir sorgudur; draw başına değil, allocation baskısında veya bir zamanlayıcıda poll edin.

Bu serideki tüm kaynak kod CC0 1.0 Universal (CC0-1.0) altında yayımlanmıştır — kamu malı tahsisi, atıf gerekmez.


Check out similar posts by category: C++ Vulkan