Unity 검색

Burst 1.7로 더 개선된 게임 개발

2022년 3월 14일 엔진 & 플랫폼 | 9 분 소요
Hardware Header
Hardware Header
다루는 주제
공유

Is this article helpful for you?

Thank you for your feedback!

최신 버전의 Burst 패키지에서는 반복 작업 시간과 Burst Inspector가 모두 대폭 개선되었습니다. 이 포스팅에서는 새로운 버전에서 변경된 사항과 HPC#(High Performance C#, 고성능 C#) 컴파일러 기술이 더 쉽게 모든 플랫폼에서 성능을 개선하는 방법을 살펴보겠습니다.

유니티의 DOTS 기술 스택은 Burst를 활용하여 고도로 최적화된 코드를 제공하며, Burst는 Unity 2019.4 이상에서 사용할 수 있는 스탠드얼론 패키지로 패키지 관리자에서 다운로드할 수 있습니다. 모든 주요 데스크톱, 콘솔, 모바일 플랫폼에서 수천 개의 프로젝트에 이미 Burst가 사용되고 있습니다.

 

반복 작업 시간 개선

이전 Burst 릴리스에서 유니티는 Burst 작업 경험을 상당히 개선했습니다. Burst 1.7에서도 역시 반복 작업 시간을 개선하는 데 중점을 두었습니다. 흔히 반복 작업 시간이란 개발의 '내부 루프'를 말합니다. C# 스크립트를 변경하고, 에디터로 돌아와서 스크립트 컴파일과 버스트 컴파일이 끝날 때까지 기다리고, 또 플레이 모드에서 변경사항을 테스트하는 작업 등이 여기에 포함됩니다.

Burst 1.7에서는 게임 코드를 몇 가지 수정하고 플레이 모드에서 테스트하는 흔한 시나리오에서 버스트 컴파일에 소모되는 시간을 대폭 줄였습니다. 이제 파이프라인에서 더 일찍(스크립트 컴파일 파이프라인이 .NET 어셈블리 컴파일을 완료한 직후) 버스트 컴파일을 진행하므로 대부분의 경우에 결과 코드를 실행해야 할 때쯤이면 버스트 컴파일이 완료됩니다. 이전 버전의 Burst에서처럼 각 버스트 진입점을 개별적으로 컴파일하지 않는 대신 이제 잡 또는 함수 포인터 등의 버스트 진입점을 배칭하여 컴파일러 처리량을 개선하고 에디터에서 로드해야 하는 라이브러리 수를 줄였습니다.

Burst 1.7에서는 Direct Call 성능도 대폭 개선되었습니다. Direct Call은 Burst 1.5에 추가된 기능으로, 관리되는 C# 코드가 BurstCompiler.CompileFunctionPointer를 거치지 않고도 버스트 컴파일된 메서드를 직접 호출할 수 있는 기능입니다. 도메인 리로드 중에 직접 호출 메서드에 연결하려면 몇 가지 초기화 작업을 거쳐야 하며, Burst 1.7에서는 이러한 초기화 작업을 최대 33배 빠르게 진행할 수 있습니다.

반복 작업 시간에 관해 마지막으로 SharedStatic 초기화 비용을 개선했습니다. SharedStatic은 관리되는 C#과 HPC# 사이에서 데이터를 공유할 수 있는 메커니즘입니다. Burst 1.7에서는 SharedStatic 초기화를 최대 13배 빠르게 진행할 수 있습니다. 

아래 그래프들은 Burst 1.7의 개선된 성능을 Burst 1.6의 성능과 비교한 결과를 보여줍니다. 해당 수치는 대규모 고객 프로젝트를 통해 측정되었습니다. 첫 번째 그래프는 System.Diagnostics.Stopwatch가 아닌 실제 스톱워치로 에디터를 관찰하여 측정한 시간을 보여주므로 일상적인 사용 상황에서 실제로 기대할 수 있는 개선 사항을 반영합니다.

Burst 1.7 performance improvements

두 번째 그래프는 Burst만 측정한 것으로 에디터에서 발생할 수 있는 다른 부분은 제외되었습니다. 측정 대상인 프로젝트와 수정된 파일의 경우 Burst 1.7은 세 가지 분야에서 전부 Burst 1.6보다 빨랐습니다.

  • 콜드 캐시(Cold Cache) - Burst가 아직 프로젝트의 코드에 대한 컴파일 결과를 캐시하지 않았습니다.
  • 웜 캐시(Warm Cache) - Burst가 이미 프로젝트에서 코드를 컴파일했으며 캐시된 컴파일 결과를 디스크에서 로드해야 합니다.
  • 단일 파일 변경(Change one file) - 한 개의 파일이 변경된 후 Burst가 재컴파일해야 하는 진입점을 파악하고 파일을 컴파일합니다. Burst 1.7의 개선 정도는 일반적으로 어떤 파일이 변경되었는지에 따라 다릅니다. 예를 들어 모든 버스트 진입점에서 사용하는 메서드를 변경하면 Burst 1.6과 Burst 1.7 간의 격차가 줄어듭니다. 이 예에서는 진입점 메서드 자체가 변경되었습니다.
Burst 1.7 performance improvements 2

Burst Inspector

Jobs > Burst > Open Inspector…에서 액세스할 수 있는 Burst Inspector는 최적화 작업에 매우 유용한 툴입니다. Burst Inspector를 사용하면 타겟 CPU에서 실행될 어셈블리 코드를 확인할 수 있습니다. Burst 1.7에는 많은 요청을 받은 기능도 몇 가지 추가되었습니다. 아래 스크린샷을 확인해 보세요.

Burst Inspector branch markers
브랜치 마커를 보여주는 Burst Inspector 스크린샷

위 이미지에서 볼 수 있듯이 브랜치 마커가 추가되어 코드 실행 경로를 더 쉽게 시각화할 수 있습니다. 브랜치 마커는 'Show Branch Flow' 체크박스로 비활성화할 수 있으므로 필요하지 않을 때는 이 기능을 끌 수 있습니다. 이 기능의 특징적인 장점 중 하나는, 브랜치 플로 화살표를 클릭하면 아래 이미지와 같이 화살표의 반대편 끝으로 이동할 수 있습니다.

브랜치 마커를 클릭하여 브랜치 목표 지점으로 이동하는 예

지시문이나 상수 데이터 등 덜 중요한 디스어셈블리 블록이 이제 자동으로 축소되며, 토글로 전환하면 다시 해당 블록을 확인할 수 있습니다.

또한 Burst 1.7에는 디스어셈블리 일부만 선택하여 복사할 수 있는 새로운 기능이 추가되었습니다.

특정 디스어셈블리 섹션만 선택하여 복사하는 예

 

기타 개선 사항

다음은 Burst 1.7의 기타 개선 사항입니다.

  • Arm Neon vst1* API를 이제 완벽하게 지원합니다. 유니티에서는 Burst 1.6에 이 API를 추가했으나, 실험적인 #define으로 보호했습니다. Burst 1.7에서는 #define으로 보호되지 않으며 완벽하게 지원됩니다.
  • System.Span<T>와 System.ReadOnlySpan<T>를 이제 버스트 코드에서 지원합니다. 이 유형은 진입점 인수로 사용할 수 없습니다.
  • Burst가 이제 기본적으로 LLVM 버전 12.0.0을 사용하여 LLVM 프로젝트의 최신 최적화 개선 사항을 구현합니다.
  • 루프 벡터라이저 이후에만 루프 언롤러를 실행하도록 LLVM 최적화 파이프라인을 변경했습니다. 이는 다양한 사례에서 코드 생성을 개선합니다.
  • FMOD와 부동 소수점 계수가 더 빠른 알고리즘을 사용하도록 만들어 성능을 개선했습니다.
  • Burst가 정적 생성자 사용으로 인해 런타임에 심볼이 누락되는 IL 스트리핑을 방지하기 위해 이제 자동으로 link.xml 링크를 생성합니다.
  • 로드/저장이 MOV 명령으로 안전하게 변환될 수 있는 경우를 더 많이 감지하여 구조체를 대규모로 복사할 때의 컴파일러 성능을 개선했습니다.
  • Burst 메뉴에서 'Show Timings' 옵션이 활성화되어 있을 때 타이밍을 표시하는 방식을 변경했습니다. 이제 더 명확한 방식으로 정보를 정리하고 제공합니다.

Burst의 향후 계획

Burst 1.7은 Unity 2019.4를 지원하는 마지막 버전입니다. 다음 Burst 버전부터는 최소한 Unity 2020.3 이상이 필요합니다. Burst에 관한 의견이나 질문, Burst를 활용하여 진행 중인 작업에 관한 이야기 등 Burst 포럼에 메시지를 남겨주세요.

2022년 3월 14일 엔진 & 플랫폼 | 9 분 소요

Is this article helpful for you?

Thank you for your feedback!

다루는 주제