Co nowego w WebGPU (Chrome 120)

François Beaufort
François Beaufort

Obsługa 16-bitowych wartości zmiennoprzecinkowych w WGSL

W WGSL typ f16 to zbiór 16-bitowych wartości zmiennoprzecinkowych w formacie binarnym IEEE-754 (półprecyzyjnym). Oznacza to, że do reprezentowania liczb zmiennoprzecinkowych używa 16 bitów, a nie 32 bitów, jak w przypadku konwencjonalnych liczb zmiennoprzecinkowych o pojedynczej precyzji (f32). Mniejsza wielkość może prowadzić do znacznego zwiększenia wydajności, zwłaszcza podczas przetwarzania dużych ilości danych.

Dla porównania, na urządzeniu Apple M1 Pro implementacja f16 modeli Llama2 7B używana w demo czatu WebLLM jest znacznie szybsza niż implementacja f32. Potwierdzają to zrzuty ekranu poniżej, które pokazują, że szybkość wypełniania wstępnego wzrosła o 28%, a szybkość dekodowania – o 41%.

Zrzut ekranu pokazujący demonstracje czatu WebLLM z modelami Llama2 7B f32 i f16.
Demo czatu WebLLM z modelami Llama2 7B f32 (po lewej) i f16 (po prawej).

Nie wszystkie procesory graficzne obsługują 16-bitowe wartości zmiennoprzecinkowe. Gdy funkcja "shader-f16" będzie dostępna w GPUAdapter, możesz poprosić o GPUDevice z tą funkcją i utworzyć moduł shadera WGSL, który korzysta z typu zmiennoprzecinkowego o półprecyzji f16. Ten typ jest prawidłowy do użycia w module shadera WGSL tylko wtedy, gdy włączysz rozszerzenie WGSL f16 za pomocą enable f16;. W przeciwnym razie funkcja createShaderModule() wygeneruje błąd weryfikacji. Zobacz ten minimalny przykład i issue dawn:1510.

const adapter = await navigator.gpu.requestAdapter();
if (!adapter.features.has("shader-f16")) {
  throw new Error("16-bit floating-point value support is not available");
}
// Explicitly request 16-bit floating-point value support.
const device = await adapter.requestDevice({
  requiredFeatures: ["shader-f16"],
});

const code = `
  enable f16;

  @compute @workgroup_size(1)
  fn main() {
    const c : vec3h = vec3<f16>(1.0h, 2.0h, 3.0h);
  }
`;

const shaderModule = device.createShaderModule({ code });
// Create a compute pipeline with this shader module
// and run the shader on the GPU...

W kodzie modułu shadera WGSL można obsługiwać typy f16f32 za pomocą alias w zależności od obsługi funkcji "shader-f16", jak pokazano w tym fragmencie kodu.

const adapter = await navigator.gpu.requestAdapter();
const hasShaderF16 = adapter.features.has("shader-f16");

const device = await adapter.requestDevice({
  requiredFeatures: hasShaderF16 ? ["shader-f16"] : [],
});

const header = hasShaderF16
  ? `enable f16;
     alias min16float = f16;`
  : `alias min16float = f32;`;

const code = `
  ${header}

  @compute @workgroup_size(1)
  fn main() {
    const c = vec3<min16float>(1.0, 2.0, 3.0);
  }
`;

Przekrocz granice

Maksymalna liczba bajtów niezbędnych do przechowywania 1 próbki (piksela lub subpiksela) danych wyjściowych renderowanego potoku dla wszystkich załączników w kolorze, domyślnie wynosi 32 bajty. Teraz możesz poprosić o maksymalnie 64 osoby, korzystając z limitu maxColorAttachmentBytesPerSample. Zapoznaj się z tym przykładem i z problemem dawn:2036.

const adapter = await navigator.gpu.requestAdapter();

if (adapter.limits.maxColorAttachmentBytesPerSample < 64) {
  // When the desired limit isn't supported, take action to either fall back to
  // a code path that does not require the higher limit or notify the user that
  // their device does not meet minimum requirements.
}

// Request highest limit of max color attachments bytes per sample.
const device = await adapter.requestDevice({
  requiredLimits: { maxColorAttachmentBytesPerSample: 64 },
});

Na wszystkich platformach zwiększyliśmy limity maxInterStageShaderVariables i maxInterStageShaderComponents używane do komunikacji między etapami. Szczegółowe informacje znajdziesz w artykule Data problemu:1448.

Na każdym etapie cieniowania maksymalna liczba wpisów układu grup powiązań w układzie potoku, które są buforami pamięci masowej, wynosi domyślnie 8. Teraz możesz poprosić o maksymalnie 10 kart, korzystając z limitu maxStorageBuffersPerShaderStage. Zobacz issue dawn:2159.

Dodano nowy limit maxBindGroupsPlusVertexBuffers. Składa się z maksymalnej liczby slotów grupy wiązania i bufora wierzchołków używanych jednocześnie, z uwzględnieniem pustych slotów poniżej najwyższego indeksu. Wartością domyślną jest 24. Zobacz problem: świt:1849.

Zmiany stanu głębokości i kratki

Ze względu na wygodę programistów atrybuty głębi szablonu depthWriteEnabled i depthCompare nie zawsze są już wymagane: element depthWriteEnabled jest wymagany tylko w przypadku formatów z głębokością, a element depthCompare nie jest wymagany w przypadku formatów z głębią, jeśli nie jest w ogóle używany. Zobacz issue dawn:2132.

Aktualizacje informacji o adapterze

Niestandardowe atrybuty informacji o adapterze typebackend są teraz dostępne po wywołaniu funkcji requestAdapterInfo(), gdy użytkownik włączy opcję „Funkcje dla deweloperów WebGPU” w sekcji chrome://flags/#enable-webgpu-developer-features. type może mieć wartość „oddzielny GPU”, „zintegrowany GPU”, „CPU” lub „nieznany”. Wartość backend to „WebGPU”, „D3D11”, „D3D12”, „metal”, „vulkan”, „openGL”, „openGLES” lub „null”. Zobacz issue dawn:2112issue dawn:2107.

Zrzut ekranu strony https://webgpureport.org z informacjami o backendzie i typie karty
Backend i typ informacji o karcie są wyświetlane na stronie https://webgpureport.org.

Opcjonalny parametr listy unmaskHints w metodzie requestAdapterInfo() został usunięty. Zobacz issue dawn:1427.

Kwantyzowanie zapytań dotyczących sygnatury czasowej

Zapytania o sygnatury czasowe umożliwiają aplikacjom pomiar czasu wykonywania poleceń GPU z dokładnością do nanosekund. Jednak specyfikacja WebGPU sprawia, że zapytania o sygnaturę czasową są opcjonalne ze względu na ataki oparte na czasie. Zespół Chrome uważa, że kwantyzacja zapytań dotyczących sygnatury czasowej zapewnia dobry kompromis między dokładnością a bezpieczeństwem, ponieważ zmniejsza rozdzielczość do 100 mikrosekund. Zobacz problem świt:1800.

W Chrome użytkownicy mogą wyłączyć kwantyzację sygnatury czasowej, włączając flagę „Funkcje dla deweloperów WebGPU” na stronie chrome://flags/#enable-webgpu-developer-features. Pamiętaj, że to oznaczenie nie włącza funkcji "timestamp-query". Jego implementacja jest wciąż eksperymentalna, dlatego wymaga ustawienia flagi „Unsafe WebGPU Support” (niebezpieczne obsługi WebGPU) w chrome://flags/#enable-unsafe-webgpu.

W Dawn dodano nowy przełącznik urządzenia o nazwie „timestamp_quantization”, który jest domyślnie włączony. Ten fragment kodu pokazuje, jak podczas wysyłania żądania dotyczącego urządzenia włączyć eksperymentalną funkcję „zapytanie o sygnaturę czasową” bez kwantyzacji sygnatury czasowej.

wgpu::DawnTogglesDescriptor deviceTogglesDesc = {};

const char* allowUnsafeApisToggle = "allow_unsafe_apis";
deviceTogglesDesc.enabledToggles = &allowUnsafeApisToggle;
deviceTogglesDesc.enabledToggleCount = 1;

const char* timestampQuantizationToggle = "timestamp_quantization";
deviceTogglesDesc.disabledToggles = &timestampQuantizationToggle;
deviceTogglesDesc.disabledToggleCount = 1;

wgpu::DeviceDescriptor desc = {.nextInChain = &deviceTogglesDesc};

// Request a device with no timestamp quantization.
myAdapter.RequestDevice(&desc, myCallback, myUserData);

Wiosenne porządki

Eksperymentalna funkcja „timestamp-query-inside-passes” została zmieniona na „chromium-experimental-timestamp-query-inside-passes”, aby poinformować deweloperów, że jest to funkcja eksperymentalna i obecnie jest dostępna tylko w przeglądarkach opartych na Chromium. Zobacz problem: świt:1193.

Funkcja „pipeline-statistics-query”, która została wdrożona tylko częściowo, została usunięta, ponieważ nie jest już rozwijana. Zobacz problem chromium:1177506.

Obejmuje to tylko niektóre najważniejsze informacje. Zapoznaj się z pełną listą commitów.

Co nowego w WebGPU

Lista wszystkiego, co zostało omówione w serii Co nowego w WebGPU.

Chrome 131

Chrome 130

Chrome 129

Chrome 128

Chrome 127

Chrome 126

Chrome 125

Chrome 124

Chrome 123

Chrome 122

Chrome 121

Chrome 120

Chrome 119

Chrome 118

Chrome 117

Chrome 116

Chrome 115

Chrome 114

Chrome 113