데이터를 GPU에 두기

데이터를 GPU에 두기

커널 함수 세 개와, 이를 resident() 배열 위에서 이어 부르는 호스트입니다. decay와 accumulate 호출은 큐에 들어가기만 합니다. 배열은 장치의 버퍼에 그대로 남고, 다음 호출이 같은 버퍼를 바인딩합니다. 호스트는 sum을 기다릴 때 한 번만 기다리고, read()로 배열을 한 번만 읽어 온다(규칙 11.8).

실행 tier WebGPUCPU tier

이 목록은 컴파일러가 확인합니다. tier(호출이 실행되는 백엔드)는 호스트의 실행 전체가 그 tier 하나만으로 기준값을 낼 때만 목록에 오릅니다. 컴파일러의 저니 게이트가 호스트마다 WebGPU와 WebGL2에서 실행하고, 단위 테스트가 CPU tier에서 실행합니다.

"use typeshade";
/* @example
{
"title": "Host: keep data on the GPU",
"blurb": "Three kernel functions and a host that chains them over `resident()` arrays. Each `decay` and `accumulate` call only queues: the array stays in its buffer on the device, and the next call binds the same buffer. The host waits once, for `sum`, and reads the array back once, with `read()` (Rule 11.8).",
"renderable": false,
"reason": "no entry point"
}
*/
// Each loop writes only its own element, so each runs on the GPU, one invocation per element.
export function decay(k: f32, ys: array<f32>) {
for (let i: u32 = 0; i < ys.length; i++) {
ys[i] = ys[i] * k;
}
}
export function accumulate(xs: array<f32>, ys: array<f32>) {
for (let i: u32 = 0; i < ys.length; i++) {
ys[i] = ys[i] + xs[i];
}
}
// A reduction, folded by the workgroup tree on the GPU.
export function sum(xs: array<f32>): f32 {
let s = 0.;
for (const x of xs) {
s += x;
}
return s;
}
// Chain kernel calls over arrays that stay on the GPU (surface §65, Rule 11.8).
//
// `resident(value)` wraps a host value once. The first call on WebGPU uploads it; the calls
// after bind the same buffer and read nothing back. A call whose written arrays are all
// resident, and that returns nothing, only queues: nothing waits on it.
import { resident } from 'typeshade/runtime';
import { accumulate, decay, sum } from './host-resident.shade.ts';
/** Run `steps` steps of `ys = ys * 0.5 + xs` on the GPU, then read the result once. */
export async function run(n = 1024, steps = 8): Promise<{ values: Float32Array; total: number }> {
const xs = resident(Float32Array.from({ length: n }, (_, i) => (i % 8) / 8));
const ys = resident(n, 'f32'); // zeros: no host copy and no upload until a call writes it
for (let step = 0; step < steps; step++) {
decay(0.5, ys); // queued
accumulate(xs, ys); // queued, after decay
}
const total = await sum(ys); // waits for the chain, and reads one number
const values = await ys.read(); // the one read of the array
xs.destroy();
ys.destroy();
return { values, total };
}

두 파일 모두 커밋 91c2fe31의 컴파일러에 있는 그대로이며, 예제 디렉터리에서 읽어 왔습니다.

GitHub의 모듈GitHub의 호스트 파일

이 페이지 편집 문제 보고