Co nowego w WebGPU (Chrome 120)

François Beaufort
François Beaufort

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

W WGSL typ f16 to zbiór 16-bitowych wartości zmiennoprzecinkowych formatu binarnego IEEE-754 (połowa precyzji). Oznacza to, że do reprezentowania liczby zmiennoprzecinkowej używa się 16 bitów, a nie 32 bitów w przypadku konwencjonalnych liczb zmiennoprzecinkowych 1-precyzyjnych (f32). Mniejszy rozmiar może prowadzić do znacznego poprawy wydajności, zwłaszcza przy przetwarzaniu dużych ilości danych.

Dla porównania: na urządzeniu Apple M1 Pro implementacja modeli Llama2 7B użytych w prezentacji czatu WebLLM jest znacznie szybsza niż w przypadku implementacji f32. Szybkość wstępnego uzupełniania wzrosła o 28%, a szybkość dekodowania o 41%, co widać na poniższych zrzutach ekranu.f16

Zrzut ekranu z wersjami demonstracyjnymi czatu WebLLM z modelami F32 i F16 Llama2 7B.
Wersje demonstracyjne czatu WebLLM z modelami f32 (po lewej) i f16 (po prawej) Llama2 7B.

Nie wszystkie procesory graficzne obsługują 16-bitowe wartości zmiennoprzecinkowe. Gdy funkcja "shader-f16" będzie dostępna w GPUAdapter, możesz wysłać żądanie GPUDevice z tą funkcją i utworzyć moduł cieniowania WGSL wykorzystujący typ zmiennoprzecinkowy o połowie precyzji f16. Tego typu można używać w module cieniowania WGSL tylko wtedy, gdy włączysz rozszerzenie f16 WGSL z enable f16;. W przeciwnym razie funkcja createShaderModule() wygeneruje błąd weryfikacji. Zobacz ten minimalny przykład: świt problemu: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 cieniowania WGSL można obsługiwać zarówno typy f16, jak i f32 za pomocą kodu alias (w zależności od obsługi funkcji "shader-f16"), jak pokazano w tym fragmencie.

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 przykładowego (piksela lub subpiksela) danych wyjściowych potoku renderowania (w przypadku wszystkich przyłączy kolorów) wynosi domyślnie 32 bajty. Teraz można poprosić o ich maksymalnie 64, korzystając z limitu maxColorAttachmentBytesPerSample. Zobacz ten przykład i problem: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 },
});

Limity maxInterStageShaderVariables i maxInterStageShaderComponents używane na potrzeby komunikacji między etapami zostały zwiększone na wszystkich platformach. Aby dowiedzieć się więcej, zobacz ten problem:1448.

Dla każdego etapu cieniowania maksymalna liczba wpisów układu grup powiązań w układzie potoku, które są buforami pamięci, wynosi domyślnie 8. Teraz można poprosić o ich maksymalnie 10, korzystając z limitu maxStorageBuffersPerShaderStage. Zobacz świt problemu:2159.

Dodano nowy limit maxBindGroupsPlusVertexBuffers. Składa się z maksymalnej liczby przedziałów grupy powiązań i przedziałów bufora wierzchołków używanych jednocześnie, licząc wszystkie puste przedziały poniżej najwyższego indeksu. Wartością domyślną jest 24. Zobacz Data wydania:1849.

Zmiany stanu szablonu głębi

Aby zwiększyć wygodę programistów, atrybuty stanu głębi (depthWriteEnabled i depthCompare) nie zawsze są już wymagane. Atrybut depthWriteEnabled jest wymagany tylko w przypadku formatów z głębokością, a depthCompare w przypadku formatów z głębokością, jeśli nie jest używany. Zobacz świt problemu:2132.

Aktualizacje informacji o adapterze

Niestandardowe atrybuty informacji o adapterach type i backend są teraz dostępne po wywołaniu funkcji requestAdapterInfo(), gdy użytkownik włączył flagę „funkcji dla programistów WebGPU” na poziomie chrome://flags/#enable-webgpu-developer-features. Pole type może mieć wartość „dyskretny GPU”, „zintegrowany GPU”, „CPU” lub „nieznany”. Element backend to „WebGPU”, „D3D11”, „D3D12”, „metal”, „vulkan”, „openGL”, „openGLES” lub „null”. Zobacz świt problemu:2112 i Data wydania:2107.

Zrzut ekranu strony https://webgpureport.org z podanym backendem i informacjami o adapterze
backend i typ informacji o adapterze podane na stronie https://webgpureport.org.

Opcjonalny parametr listy unmaskHints w funkcji requestAdapterInfo() został usunięty. Zobacz świt problemu:1427.

Kwantyzowanie zapytań z sygnaturą czasową

Zapytania dotyczące sygnatury czasowej pozwalają aplikacjom mierzyć czas wykonywania poleceń GPU z dokładnością nanosekundową. Specyfikacja WebGPU sprawia, że zapytania o sygnaturę czasową są jednak opcjonalne ze względu na obawy o atak w czasie. Zespół Chrome uważa, że kwantyfikacja zapytań z sygnaturami czasowymi zapewnia dobry kompromis między precyzją a bezpieczeństwem, ponieważ zmniejsza rozdzielczość do 100 mikrosekund. Zobacz Data problemu:1800.

W Chrome użytkownicy mogą wyłączyć kwantyzację sygnatury czasowej, włączając flagę „Funkcje dla programistów WebGPU” na stronie chrome://flags/#enable-webgpu-developer-features. Pamiętaj, że ta flaga nie włącza funkcji "timestamp-query". Implementacja tej metody jest nadal w fazie eksperymentalnej i dlatego wymaga umieszczenia flagi „Unsafe WebGPU Support” (Obsługa niebezpiecznej technologii WebGPU) na stronie chrome://flags/#enable-unsafe-webgpu.

W aplikacji Dawn dodano nowy przełącznik urządzenia o nazwie „timestamp_quantization”, który jest domyślnie włączony. Poniższy fragment kodu pokazuje, jak zezwolić na eksperymentalną funkcję „zapytanie z sygnaturą czasową” bez kwantyzacji sygnatury czasowej, gdy wysyłasz żądanie udostępnienia urządzenia.

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);

Funkcje wiosennego porządków

Eksperymentalna funkcja „timestamp-query-inside-passes” została zmieniona na „chromium-experimental-timestamp-query-inside-passes”, aby programiści wiedzieli, że jest to funkcja eksperymentalna, która jest obecnie dostępna tylko w przeglądarkach opartych na Chromium. Zobacz świt problemu:1193.

Eksperymentalna funkcja „pipeline-statists-query”, która została wdrożona tylko częściowo, została usunięta, ponieważ nie jest już opracowywana. Zobacz issue chromium:1177506.

To tylko niektóre z najważniejszych kwestii. Zobacz pełną listę zatwierdzeń.

Co nowego w WebGPU

Lista wszystkich zagadnień omówionych w serii Co nowego w WebGPU.

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