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 liczby zmiennoprzecinkowej 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 potrzebna do przechowywania jednej próbki (piksel lub subpiksel) danych wyjściowych z pipeline’u renderowania we wszystkich załącznikach kolorów to domyślnie 32 bajty. Teraz możesz poprosić o maksymalnie 64 poziomy, korzystając z limitu maxColorAttachmentBytesPerSample. Zobacz poniższy przykład i problem 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. Więcej informacji znajdziesz w issue dawn:1448.

W przypadku każdego etapu shadera maksymalna liczba wpisów w układzie grupy wiązania w układzie przepływu, które są buforami danych, 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, licząc puste sloty poniżej najwyższego indeksu. Wartością domyślną jest 24. Zobacz issue dawn:1849.

Zmiany stanu głębokości i kratki

Aby ułatwić pracę deweloperom, atrybuty stan warstwy głębokości depthWriteEnableddepthCompare nie są już zawsze wymagane: depthWriteEnabled jest wymagany tylko w przypadku formatów z głębią, a depthCompare nie jest wymagany w przypadku formatów z głębią, jeśli nie jest używany. Zobacz issue dawn:2132.

Aktualizacje informacji o adapterze

Atrybuty informacji o niestandardowych adapterach 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. Wartość type może być „GPU dyskretny”, „GPU zintegrowany”, „Procesor” 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
Informacje o adapterze i typ backendu 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 sygnatury czasowe 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 issue dawn:1800.

W Chrome użytkownicy mogą wyłączyć kwantyzację sygnatury czasowej, włączając flagę „WebGPU dla deweloperów” na stronie chrome://flags/#enable-webgpu-developer-features. Pamiętaj, że ten flaga sama w sobie 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. W tym fragmencie kodu pokazano, jak zezwolić na eksperymentalną funkcję „zapytanie o sygnaturę czasową” bez kwantowania sygnatury czasowej podczas wysyłania żądania do 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);

Wiosenne porządki

Eksperymentalna funkcja „timestamp-query-inside-passes” została przemianowana na „chromium-experimental-timestamp-query-inside-passes”, aby wyraźnie poinformować deweloperów, że jest to funkcja eksperymentalna i obecnie jest dostępna tylko w przeglądarkach opartych na Chromium. Zobacz issue dawn: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 wszystkich tematów omawianych w cyklu 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