WebGPU: 브라우저에서 최신 GPU 액세스 활용

WebGPU가 GPU의 성능을 활용하여 머신러닝 성능을 높이고 그래픽 렌더링을 개선하는 방법을 알아보세요.

새로운 WebGPU API를 사용하면 그래픽 및 머신러닝 워크로드에서 성능이 대폭 향상됩니다. 이 도움말에서는 WebGPU가 현재의 WebGL 솔루션보다 어떻게 개선되었는지 살펴보고 향후 개발에 관해 살짝 살펴봅니다. 하지만 먼저 WebGPU가 개발된 이유에 대한 맥락을 제공해 보겠습니다.

WebGPU의 컨텍스트

2011년 Chrome에 WebGL이 도입되었습니다. WebGL은 웹 애플리케이션이 GPU를 활용할 수 있도록 허용하여 Google 어스, 양방향 뮤직비디오, 3D 부동산 둘러보기 등 웹에서 놀라운 환경을 제공합니다. WebGL은 1992년에 처음 개발된 OpenGL API 제품군을 기반으로 합니다. 오래전 일이네요. 그 이후로 GPU 하드웨어는 크게 발전했습니다.

이러한 진화를 따라잡기 위해 최신 GPU 하드웨어와 더 효율적으로 상호작용할 수 있는 새로운 API가 개발되었습니다. Direct3D 12, Metal, Vulkan 등의 API 이러한 새로운 API는 머신러닝의 폭발적인 증가와 렌더링 알고리즘의 발전과 같은 GPU 프로그래밍의 까다로운 새로운 사용 사례를 지원했습니다. WebGPU는 WebGL의 후속 버전으로, 이 새로운 클래스의 최신 API의 개선사항을 웹에 제공합니다.

WebGPU를 사용하면 브라우저에서 다양한 새로운 GPU 프로그래밍 가능성을 활용할 수 있습니다. 최신 GPU 하드웨어의 작동 방식을 더 잘 반영하는 동시에 향후 더 고급 GPU 기능을 위한 기반을 마련합니다. 이 API는 2017년부터 W3C의 '웹용 GPU' 그룹에서 개발 중이며 Apple, Google, Mozilla, Microsoft, Intel과 같은 여러 회사 간의 공동작업입니다. 6년간의 노력 끝에 웹 플랫폼에 가장 큰 추가 기능 중 하나가 드디어 제공됩니다.

WebGPU는 현재 ChromeOS, macOS, Windows의 Chrome 113에서 사용할 수 있으며 다른 플랫폼도 곧 지원될 예정입니다. 이 작업을 도와주신 다른 Chromium 참여자와 특히 Intel에 감사드립니다.

이제 WebGPU로 지원되는 몇 가지 흥미로운 사용 사례를 살펴보겠습니다.

렌더링을 위한 새로운 GPU 워크로드 활용

컴퓨팅 셰이더와 같은 WebGPU 기능을 사용하면 새로운 클래스의 알고리즘을 GPU로 포팅할 수 있습니다. 예를 들어 장면에 더 역동적인 세부정보를 추가하거나 물리적 현상을 시뮬레이션하는 등의 알고리즘이 있습니다. 이전에는 JavaScript로만 수행할 수 있었던 워크로드도 이제는 GPU로 옮길 수 있습니다.

다음 동영상에서는 이러한 메타볼의 표면을 삼각형화하는 데 사용되는 행진 큐브 알고리즘을 보여줍니다. 동영상의 처음 20초 동안 JavaScript에서 실행되는 알고리즘이 8FPS로만 실행되는 페이지를 따라잡지 못해 버벅거리는 애니메이션이 발생합니다. JavaScript에서 성능을 유지하려면 세부 수준을 크게 낮춰야 합니다.

동일한 알고리즘을 컴퓨팅 셰이더로 이동하면 천지 차이가 납니다. 이는 동영상 20초 후에 확인할 수 있습니다. 이제 페이지가 부드럽게 60FPS로 실행되므로 성능이 크게 개선되었으며 다른 효과를 위한 성능 여유도 많이 남아 있습니다. 또한 페이지의 기본 JavaScript 루프가 다른 작업을 위해 완전히 확보되므로 페이지와의 상호작용이 계속 반응합니다.

메타볼 데모

또한 WebGPU를 사용하면 이전에는 실용적이지 않았던 복잡한 시각적 효과를 사용할 수 있습니다. 인기 있는 Babylon.js 라이브러리에서 만든 다음 예시에서는 바다 표면이 GPU에서 완전히 시뮬레이션됩니다. 사실적인 역학은 여러 개의 독립적인 파도가 서로 추가되어 만들어집니다. 하지만 각 웨이브를 직접 시뮬레이션하는 것은 비용이 너무 많이 듭니다.

해양 데모

따라서 이 데모에서는 빠른 푸리에 변환이라는 고급 알고리즘을 사용합니다. 모든 파동을 복잡한 위치 데이터로 표현하는 대신 계산 수행에 훨씬 더 효율적인 스펙트럼 데이터를 사용합니다. 그런 다음 각 프레임은 푸리에 변환을 사용하여 스펙트럼 데이터를 파장의 높이를 나타내는 위치 데이터로 변환합니다.

더 빠른 ML 추론

WebGPU는 최근 GPU의 주요 사용 사례가 된 머신러닝을 가속화하는 데도 유용합니다.

오랫동안 크리에이티브 개발자는 머신러닝 계산과 같은 렌더링 이외의 작업을 실행하기 위해 WebGL의 렌더링 API를 재사용해 왔습니다. 하지만 이렇게 하려면 계산을 시작하는 방법으로 삼각형의 픽셀을 그리고 더 범용적인 메모리 액세스 대신 텍스처에서 텐서 데이터를 신중하게 패킹 및 unpacking해야 합니다.

중복 메모리 로드, 중복 계산, 스레드당 작성되는 값이 적은 등 WebGL을 사용한 단일 ML 연산자 실행의 비효율성을 보여주는 그림입니다.
WebGL을 사용한 단일 ML 연산자 실행.

이러한 방식으로 WebGL을 사용하려면 개발자가 코드를 그리기 전용으로 설계된 API의 기대치에 맞게 어색하게 조정해야 합니다. 계산 간의 공유 메모리 액세스와 같은 기본 기능이 부족한 점과 더불어 중복 작업과 최적화되지 않은 성능이 발생합니다.

컴퓨팅 셰이더는 WebGPU의 새로운 주요 기능이며 이러한 고충을 제거합니다. 컴퓨팅 셰이더는 렌더링 작업의 엄격한 구조에 제약되지 않으면서 GPU의 대규모 병렬 처리 특성을 활용하는 보다 유연한 프로그래밍 모델을 제공합니다.

공유 메모리 로드, 공유 계산, 메모리에 대한 유연한 쓰기 등 WebGPU 컴퓨팅 셰이더의 다양한 효율성 향상
WebGPU 컴퓨팅 셰이더 효율성

컴퓨팅 셰이더는 셰이더 작업 그룹 간에 데이터와 계산 결과를 더 많이 공유하여 효율성을 높입니다. 이렇게 하면 이전에 동일한 목적으로 WebGL을 사용하려던 시도에 비해 상당한 이점을 얻을 수 있습니다.

이로 인해 얻을 수 있는 효율성 향상의 예로 TensorFlow.js의 이미지 확산 모델 초기 포팅은 WebGL에서 WebGPU로 이동할 때 다양한 하드웨어에서 성능이 3배 향상되었습니다. 테스트한 일부 하드웨어에서는 이미지가 10초 이내에 렌더링되었습니다. 초기 포팅이므로 WebGPU와 TensorFlow.js 모두에서 더 많은 개선이 가능할 것으로 기대합니다. 2023년 웹 ML의 새로운 기능을 확인하세요. Google I/O 세션

그러나 WebGPU는 GPU 기능을 웹에 제공하는 것만이 아닙니다.

JavaScript를 우선으로 설계

한동안 이러한 사용 사례를 지원하는 기능은 플랫폼별 데스크톱 및 모바일 개발자에게 제공되어 왔으며, 웹 플랫폼의 자연스러운 일부처럼 느껴지는 방식으로 이러한 기능을 노출하는 것은 어려운 일이었습니다.

WebGPU는 10년 넘게 WebGL로 놀라운 작업을 해 온 개발자들의 경험을 바탕으로 개발되었습니다. 우리는 그들이 겪은 문제, 직면한 병목 현상, 그들이 제기한 문제를 파악하여 이러한 모든 피드백을 새로운 API에 전달할 수 있었습니다.

WebGL의 전역 상태 모델로 인해 강력하고 구성 가능한 라이브러리와 애플리케이션을 만들기가 어렵고 불안정하다는 것을 확인했습니다. 따라서 WebGPU는 개발자가 GPU 명령어를 전송하는 동안 추적해야 하는 상태의 양을 크게 줄입니다.

WebGL 애플리케이션을 디버깅하기가 어렵다는 의견에 따라 WebGPU에는 성능을 저하하지 않는 더 유연한 오류 처리 메커니즘이 포함되어 있습니다. 또한 API에서 반환되는 모든 메시지를 이해하기 쉽고 실행 가능하도록 만들기 위해 노력했습니다.

또한 너무 많은 JavaScript 호출을 수행하는 오버헤드가 복잡한 WebGL 애플리케이션의 병목 현상인 경우가 빈번하다는 것도 확인했습니다. 따라서 WebGPU API는 대화량이 적으므로 더 적은 수의 함수 호출로 더 많은 작업을 할 수 있습니다. 중요한 그리기 루프를 최대한 간결하게 유지하면서 대규모 유효성 검사를 미리 실행하는 데 중점을 둡니다. 또한 렌더 번들과 같은 새로운 API를 제공하여 많은 수의 그리기 명령어를 미리 녹화하고 단일 호출로 재생할 수 있습니다.

렌더링 번들과 같은 기능으로 얻을 수 있는 극적인 차이를 보여드리기 위해 Babylon.js의 또 다른 데모를 보여 드리겠습니다. WebGL 2 렌더러는 모든 JavaScript 호출을 실행하여 이 아트 갤러리 장면을 초당 약 500번 렌더링할 수 있습니다. 꽤 좋죠.

아트 갤러리

그러나 WebGPU 렌더러는 스냅샷 렌더링이라는 기능을 사용 설정합니다. WebGPU 렌더 번들을 기반으로 하는 이 기능을 사용하면 동일한 장면을 10배 이상 더 빠르게 제출할 수 있습니다. 이로 인해 오버헤드가 크게 감소하여 WebGPU가 더 복잡한 장면을 렌더링하는 동시에 애플리케이션에서 JavaScript로 더 많은 작업을 동시에 수행할 수 있습니다.

최신 그래픽 API는 단순성을 극단적인 최적화 기회로 바꾸는 복잡성으로 유명합니다. 반면 WebGPU는 크로스 플랫폼 호환성에 중점을 두고 있으며 대부분의 경우 리소스 동기화와 같이 전통적으로 어려운 주제를 자동으로 처리합니다.

이는 WebGPU를 배우고 사용하기 쉽다는 좋은 부작용을 가져옵니다. 이미지 및 동영상 로딩과 같은 작업에 웹 플랫폼의 기존 기능을 사용하고 비동기 작업에 프로미스와 같은 잘 알려진 JavaScript 패턴을 사용합니다. 따라서 필요한 상용구 코드의 양을 최소한으로 유지하는 데 도움이 됩니다. 50줄 미만의 코드로 첫 번째 삼각형을 화면에 표시할 수 있습니다.

<canvas id="canvas" width="512" height="512"></canvas>
<script type="module">
  const adapter = await navigator.gpu.requestAdapter();
  const device = await adapter.requestDevice();

  const context = canvas.getContext("webgpu");
  const format = navigator.gpu.getPreferredCanvasFormat();
  context.configure({ device, format });

  const code = `
    @vertex fn vertexMain(@builtin(vertex_index) i : u32) ->
      @builtin(position) vec4f {
       const pos = array(vec2f(0, 1), vec2f(-1, -1), vec2f(1, -1));
       return vec4f(pos[i], 0, 1);
    }
    @fragment fn fragmentMain() -> @location(0) vec4f {
      return vec4f(1, 0, 0, 1);
    }`;
  const shaderModule = device.createShaderModule({ code });
  const pipeline = device.createRenderPipeline({
    layout: "auto",
    vertex: {
      module: shaderModule,
      entryPoint: "vertexMain",
    },
    fragment: {
      module: shaderModule,
      entryPoint: "fragmentMain",
      targets: [{ format }],
    },
  });
  const commandEncoder = device.createCommandEncoder();
  const colorAttachments = [
    {
      view: context.getCurrentTexture().createView(),
      loadOp: "clear",
      storeOp: "store",
    },
  ];
  const passEncoder = commandEncoder.beginRenderPass({ colorAttachments });
  passEncoder.setPipeline(pipeline);
  passEncoder.draw(3);
  passEncoder.end();
  device.queue.submit([commandEncoder.finish()]);
</script>

결론

WebGPU가 웹 플랫폼에 제공하는 새로운 가능성을 확인할 수 있어 기쁩니다. WebGPU를 활용한 멋진 새로운 사용 사례가 많이 등장할 것으로 기대됩니다.

WebGL을 중심으로 활기찬 라이브러리 및 프레임워크 생태계가 구축되었으며, 이 생태계는 WebGPU를 기꺼이 수용하고 있습니다. WebGPU 지원은 많은 인기 있는 JavaScript WebGL 라이브러리에서 진행 중이거나 이미 완료되었습니다. 경우에 따라 WebGPU의 이점을 활용하는 것은 단일 플래그를 변경하는 것만큼 간단할 수 있습니다.

Babylon.js, Construct 3, Google Earth, Google Meet, PlayCanvas, Sketchfab, Three.JS, TensorFlow.js, Unity
완료되었거나 진행 중인 WebGPU 포트가 있는 프레임워크, 애플리케이션, 라이브러리

이번 Chrome 113의 첫 번째 출시는 시작에 불과합니다. 초기 출시는 Windows, ChromeOS, MacOS용이지만 가까운 시일 내에 Android 및 Linux와 같은 나머지 플랫폼에도 WebGPU를 제공할 계획입니다.

WebGPU 출시를 위해 노력하는 것은 Chrome팀만이 아닙니다. Firefox 및 WebKit에서도 구현이 진행 중입니다.

또한 하드웨어에서 사용할 수 있을 때 노출할 수 있는 새로운 기능이 W3C에서 이미 설계되고 있습니다. 예를 들어 Chrome에서는 머신러닝 성능을 더욱 향상시키기 위해 셰이더에서 16비트 부동 소수점 수 지원을 지원하고 곧 DP4a 클래스 명령을 지원할 계획입니다.

WebGPU는 투자하면 놀라운 성능을 발휘하는 광범위한 API입니다. 오늘은 WebGPU의 이점을 대략적으로만 다루었지만 WebGPU를 시작하려면 시작 Codelab인 첫 번째 WebGPU 앱을 확인하세요. 이 Codelab에서는 기존 Conway's Game of Life의 GPU 버전을 빌드합니다. 이 Codelab에서는 GPU 개발을 처음 하는 경우에도 사용해 볼 수 있도록 이 프로세스를 단계별로 안내합니다.

WebGPU 샘플도 API를 파악하는 데 도움이 됩니다. 기존의 'hello triangle'부터 더 완벽한 렌더링 및 컴퓨팅 파이프라인에 이르기까지 다양한 기법을 보여줍니다. 마지막으로 다른 리소스도 확인해 보세요.