[WASM] SIMD로 병렬연산 최적화하기 (with Rust)

[원본 링크]

본 포스트는 브라우저 환경에서 WASM과 SIMD을 적용하는 방법, 그리고 실제 성능 비교 결과를 기록한 글이다.

WebAssebly(이하 WASM)는 Javascript의 부족한 성능을 채우기 위해 나온 새로운 웹 표준 규격이다.

Javascript는 지나치게 보수적이고 경직된 형태로 구성된 샌드박스 위에서 동작하고, 비효율적인 타입시스템이나 구조를 가진 탓에 성능이 후달리는 부분이 많았다.
WASM은 이와 반대로 덜 엄격한 샌드박스 위에서 동작하며, 단순한 브라우저 스크립트에서 벗어나서 직접 바이너리처럼 실행되는 것을 지향한다. 정확히 말해서 CPU 수준의 인스트럭션을 적극적으로 활용해서 최적화를 할 수 있는 것이다.

WASM이 요즘 여러가지 공상적이고 실험적인 시도를 많이 하고 있어서 뜬구름잡는게 많긴 한데, 개중에서도 뚜렷하게 성과를 보이는 것이 큰 사이즈의 벡터 데이터에 대한 병렬연산이다. SIMD 인스트럭션을 사용해서 공격적인 최적화를 할 수 있기 때문이다.
https://blog.naver.com/sssang97/222705751501
이게 왜 중요하냐면, 행렬이나 무거운 바이트 시퀀스(이미지 같은 미디어 데이터)를 브라우저에서 자바스크립트로 실행하면 상당히 구린 최적화를 보여주기 때문이다.
이런걸 SIMD로 돌릴 수만 있어도 삶의 질이 달라진다. SIMD 없이 WASM만 써도 빠르다.

물론 현재로서는 환경이 완벽하지는 않긴 하다.
SIMD는 아직 WASM 표준에 들어가있지도 않은데다, 그걸 제대로 구현한 것도 크롬 말고는 딱히 없다. 브라우저 호환성을 어느정도 포기해야 한다.

한번 직접 돌려보면서 그 대략적인 사용법과 성능을 확인해보겠다.
내가 돌려본 환경은 Windows 11, AMD64(라이젠), 크롬이다.
WASM 특성상 CPU 종류, 브라우저 종류, 브라우저 버전마다 성능차가 날 수 있다. 특히 SIMD는 인텔/암드에서 가장 빠른 성능이 나오고, 그 외 환경에서는 그보단 느릴 수도 있다.

전체 예제 코드는 다음 레포지토리에 있다.
https://github.com/myyrakle/wasm_example/tree/master/simd




1. 자바스크립트만 쓰기

먼저 자바스크립트만 가지고 꽤 큰 바이트 배열의 연산을 수행해보겠다.

100메가 크기의 바이트 배열을 생성하고, 더하는 간단한 코드다.

그럼에도 불구하고

성능이 이정도 나온다. 대략 3초 정도 걸렸다. 꽤 느린 편이다.




2. WASM으로 처리하기

나는 WASM을 빌드하는데 Rust를 사용했다.
환경이 제일 좋기도 하고, 내게도 익숙하기 때문이다.

코드 자체는 자바스크립트와 크게 다를게 없다.
Rust는 간단하게 쓴다면 그다지 어려운 언어가 아니고, 이정도 단순한 코드로도 큰 성능 향상을 누릴 수 있다.

저 코드를 WASM으로 빌드한 후

자바스크립트 bond와 함께 로드해서 사용하면 된다.


그리고 이렇게 갖다썼다.


매우 빨라졌다.
3초쯤 걸리던게 1초 미만으로 처리가 된다.
자바스크립트가 얼마나 느렸는지 체감이 되는가...?




3. SIMD로 최적화하기

이걸 적용했을 때는 빨라질 수도 있고, 환경에 따라 그냥 비슷할 수도 있다.

simd로 바이트 배열을 더하는 코드다.
최대로 몰아서 처리할 수 있는 단위가 64개라서 64개씩 묶어서 SIMD 인스트럭션을 때리는 것이다. 이건 좀 복잡해보일 수 있다.

그리고 마찬가지로 빌드해서

갖다썼다.


자바스크립트에서 WASM으로 전환한 정도의 극적인 차이가 나지는 않았지만, 최적화가 더 되긴 됐다.
가끔 0.3초쯤 걸리기도 하는데, 거의 0.2초 미만으로 돌더라.


wasm 소스를 까보면 v128로 시작하는 인스트럭션이 있는데, 이게 simd 관련된 물건이다.
v128.load로 가져오고 v128.store로 결과를 저장한다. 자세히 알 필요까지는 없다.

아무튼 결과적으로 WASM만 적용했을 때는 대략 5배, SIMD까지 적용했을 때는 10배 정도의 성능 향상을 확인할 수 있었다. 실제로 미디어파일을 다루는 복잡한 유즈케이스에서는 더 큰 차이를 볼 수도 있을 것이다.

쓸만하지않은가?


참조
https://blog.naver.com/sssang97/221695435038
https://doc.rust-lang.org/std/simd/struct.Simd.html
https://blog.naver.com/sssang97/223318770087