게임 만들다 보면 "어? 프레임이 왜 떨어지지?", "왜 이 장면에서 렉이 걸리지?" 같은 순간이 온다.
그럴 때 보통은 "감"으로 고쳐보려다가 더 망하거나, 아니면 그냥 넘어가는 경우가 더 많았던 것 같다.
그래서 이번엔 정말 기초부터 메모리, SoC 같은 것들을 하나씩 정리해가면서, 작성을 해본다.
1.하드웨어
1.1 Soc
: 하드웨어의 대표적인 장치로는 연산을 위한 CPU 그래픽 연산을 위한 GPU 음성 및 영상 디지털 데이터를 처리하는 DSP 등을 들 수 있다.
대부분 데스크톱 PC는 개별적으로 가지고 있으나 모바일 기기의 특성상 소형화가 필수이다.
이렇게 위의 3개를 조합하여 만든 장치를 SOC(System_on_a_chip), 즉 SoC 라고 부른다.
1.2 아이폰, 안드로이드의 SoC
: 스마트폰은 기종에 따라 탑재되는 SoC가 다르다.
를 들어, 아이폰에는 애플이 설계한 A 시리즈라는 SoC가 사용된다. 이 시리즈는 A15 와 같이 'A'f'라는 글자와 숫자의 조합으로 명명되며, 버전이 올라갈수록 숫자가 커진다.
이에 반해 많은 안드로이드는 SnapDragon이라는 SoC를 사용하고 있다. 이는 Qualcomm 이라는 회사가 제조하는 SoC이다.
또한, 아이폰이 애플사에서 제조하는 반면, 안드로이드는 다양한 제조사들이 제조하고 있다.
따라서 Qualcomm이 제작한 SnapDragon외에도 많은 SoC를 사용하곤 한다. 안드로이드에서 기종에 따라 결함이 발생하기 쉬운 것은 바로 이 때문이다.
성능 튜닝을 할 때, 해당 단말기의 SoC가 무엇이 사용되었고, 어떤 스펙을 가지고 있는지 파악하는게 튜닝에 중요하다.
2.CPU
: CPU(Centeral Processing Unit) 진행 본부 장치(?) 는 컴퓨터 연산의 메인이라고 할 수 있는 부분이다.
프로그램 실행은 물론이고 다양한 하드웨어와의 연계를 담당하고 있다.
튜닝을 할때 CPU의 원리 및 구조를 알게되면 도움이 된다.
프로그램의 실행속도는 단순한 연산뿐만이 아니라 복잡한 프로그램을 얼마나 빠르게 실행할 수 있냐에 따라 결정이 된다.
예를 들어 프로그램에는 사칙연산이 있지만 분기처리도 있다.
CPU는 다음으로 어떤 연산을 실행할지 프로그램을 실행하기 전까지는 알지 못한다.
그래서 CPU는 다양한 명령어를 고속으로 처리할 수 있게 하드웨어가 설계되어있다.
CPU내부에서 처리가되는 흐름을 파이프라인이라고 한다.
파이프라인에서는 다음 명령어를 예측하면서 처리가 되는데 만약 다음 명령어가 예측이 되지 않다면 파이프라인 스톨이라는 일시정지가 발생하여 한 번 리셋된다.
스톨을 일으키는 원인은 대부분 분기처리이다.
분기 자체도 어느 정도 결과를 예측하겠지만 그래도 실수할 수 있다.
물론 분기처리를 안하고 기능을 만들수는 없다.
일단 인지 정도만 하면 좋을 것 같다.
2.1 CPU의 연산능력
CPU의 연산 능력은 클럭 주파수 와 코어 수로 결정이된다.
클럭 주파수는 1초당 CPU가 몇 번 이나 동작할 수 있는지 나타낸다.
따라서 클럭 주파수가 얼마나 높으냐에 따라 성능을 체크할 수 있다.
한편 코어 수는 CPU 의 병렬 연산 능력에 기여한다. 코어는 CPU가 동작하는 기본 단위이며 코어가 여러개면 멀티 코어 라고 이야기한다.
원래는 싱글 코어만 있었으나, 싱글 코어의 경우 여러 프로그램을 실행시키기 위해 번갈아가며 실행할 프로그램을 전환했는데 이를 컨텍스트 스위치라고 한다.
하지만 이는 비용이 매우 높다.
스마트폰은 실제로는 OS등 다양한 프로세스가 병렬로 처리가 되어가고 있는데
이러한 상황으로 최적의 처리를 진행하기 위해 여러개의 코어를 넣은 멀티 코어를 진행하게 되었다.
최근 멀티코어는 비대칭 코어를 탑재한 CPU가 주류를 이루고 있다.
비대칭 코어란 고성능 코어와 저전력 코어를 함께 탑재한 CPU를 말한다.
비대칭 코어는 평소에는 낮은 성능의 코어를 실행하면서 배터리 소모를 줄이고, 게임 등 성능을 내야 할 때 코어를 전환해 사용 할 수 있다.
단, 절전 코어 만큼 병렬 성능의 최대치가 떨어져 코어의 수가 성능을 판단할 수있는 부분은 아니다.
2.2 CPU의 캐시 메모리
CPU와 메인 메모리는 물리적으로 멀리 떨어져 있다.
접근하는데 약간의 시간이 필요하며 따라 프로그램 실행 시 메인 메모리에 저장된 데이터에 접근하려고 할 때 , 이 거리가 성능에 큰 병목현상이 발생하게 되는데.
이 레이턴시 문제를 해결하기 위해 CPU 내부에서는 캐시 메모리가 탑재되어 있다. 캐시 메모리는 주로 메인 메모리에 저장된 데이터의 일부를 저장하여 프로그램이 필요로 하는 데이터를 빠르게 접근할 수 있도록 한다. 캐시 메모리에는 L1~L3 캐시가 있는데 숫자가 작을수록 작은용량을 가지고 있으나 속도가 빠르다. L3캐시 용량을 예시로 들자면 2~4 MB 수준이다.
따라서 CPU 캐시에는 모든 데이터를 저장할 수 없고, 가장 최근에 처리한 데이터만 캐시된다.
3.GPU
CPU가 프로그램 실행에 특화가 되어 있다면 GPU는 렌더링(화면에 그림을 그리는 일련의 과정)에 특화된 하드웨어이다.
GPU의 기본
GPU는 그래픅 처리에 특화되어 있기 떄문에 CPU 와 구조가 크게 다르며, 간단한 계산을 대량으로 병렬로 처리할 수 있도록 설계되어 있다.
특히 그래픽 계열에서는 부동소수점 연산이 많이 필요한데 GPU는 부동소수점 연산을 자한다.
그래서 1초에 몇번이나 부동소수점 연산을 할 수 있는지를 나타내는 FLOPS라는 성능 지표가 일반적으로 사용된다.
또한, 연산 능력만으로는 알기 어렵기 떄문에 1초당 몇개의 픽셀을 그릴 수 있는지를 나타내는 필레이트라는 지표도 사용된다.
GPU의 연산 능력
GPU의 하드웨어 특징은 정수 및 부동소수점 연산 다위를 포함하는 코어가 대량(수십~수천 개)으로 배치되어 있다.
코어를 많이 배치하기 위해 CPU에서 필요했던 복잡한 프로그램을 실행하는 데 필요한 단위는 필요 없어서 생략이 되어있고
CPU처럼 클럭 주파수가 높으면 좀 더 많은 연산을 진행할 수 있다.
GPU의 메모리
GPU 도 다영히 데이터를 처리하기 위해 일시적으로 저장할 수 있는 메모리 영역이 필요하다.
보통 이 영역은 메인 메리와 달리 GPU 전용 메모리가 되는데. 따라서 어떤 처리를 하기 위해서는 메인 메모리에서 GPU의 메모리로 데이터를 전송해야 한다.처리 후에는 메인 메모리로 되돌려 놓는다.
EX) 여러 해상도의 큰 텍스처를 전송하는 등 전송량이 많을 경우 전송에 시간이 걸려 처리의 병목현상이 발생 할 수 있다.
그러나 모바일에서는 GPU 전용 메모리를 탑재하지 않고 CPU 와 GPU가 메인 메모리를 공유하는 아키텍처가 일반적이다.
이는 메모리 저장공간의 용량을 동적으로 변경할 수 있다는 장점이 있지만, 전송 대역을 CPU와 GPU가 공유한다는 단점이 있다.
또한 이 경우에도 CPU와 GPU의 메모리 영역 간 데이터 전송이 필요하다.
4.메모리
CPU는 그 순간 계산에 필요한 데이터만 가지고 있기 때문에 기본적으로는 모든 데이터는 메인 메모리에 저장된다.
물리적인 용량 이상의 메모리를 사용할 수 없어서 너무 많이 사용하면 메모리를 확보가 불가능해 OS에서 강제종료를 하곤한다.
이를 OOM으로 Kill 되었다고 한다.
5.메모리 스왑
휴대폰의 OS는 다양한 방법으로 가상의 메모리 용량을 확보하려고한다.
해당 현상을 메모리 스왑이라고 하는데
메모리 스왑에서 사용돠는 한 가지 방법이 메모리 압축이다.
한동안 접근하지 않는 메모리 중심으로 압축하여 메모리 상에 저장함으로써 물리적인 용량을 절약한다.
다만 압축과 전개 비용이 발생하기 때문에 이용이 활발한 영역이 아닌, 예를 들어 백그라운드에 있는 앱에 대해서만 수행된다.
다른 방법은 사용하지 않는 메모리의 저장소 퇴출이다.PC와 같이 스토리지가 넉넉한 하드웨어는 프로세스를 종료하여 메모리를 확보하는 것이 아니라 덜 사용되는 메모리를 스토리지로 대피시켜 물리 메모리의 여유 공간을 확보하려는 경우가 있는데.
이는 메모리 압축보다 대용량의 메모리를 확보할 수 있다는 장점이 있는데, 스토리지는 메모리보다 속도가 느리고 성능상의 제약이 심할뿐더러 스토리지가 작은 스마트폰에서는 채택이 되지 않았다.
2. 렌더링
게임에서 렌더링의 처리량은 성능에 부정적인 영향을 미친다. 따라서 튜닝에 있어서는 렌더링 관련 지식은 필수적이다.
2.1 렌더링 파이프라인
컴퓨터 그래픽스에서 렌더링 파이프 라인은 3D 모델의 버텍스의 좌표,라이트의 좌표, 색상 등의 데이터를 처리하ㅇ 화면의 각 픽셀에 맞게 출력하는 일련의 과정을 이야기 한다.
렌더링 파이프라인은 CPU에서 GPU에 보내는 것으로 시작된다.
렌더링할 3D 모델의 버텍스 좌표 라이트 좌표를 비롯해 오브젝트의 재질 정보, 카메라 정보 등 다양 한 데이터가 전송된다.
이때 전송되는 것은 각각 개별적인 데이터다.
GPU는 이 정보들을 종합해 "해당 카메라로 해당 물체를 비췄을 때 화면의 어느 위치에 물체가 표시되는지"를 계산해 구한다.
이 과정을 좌표 변환이라고 한다.
좌표가 정해지면 해당 재질의 라이트 연산을 진행한다.
위의 처리중 프래그먼트 셰이더가 있는데 해당 셰이더는 화면의 어느 위치에 오브젝트가 표시될건지는 버텍스 셰이더.
화면의 각 픽셀에 해당하는 부분은 어떤 색이 되는지는 프래그먼트 셰이더를 통해서 진행이 된다.
위에서 언급한 셰이더는 자유롭게 작성이가능하며 무거운 처리를 쓰면 처리 부하가 증가한다.
또한 버텍스 수가 많을수록 처리 부하가 커지며. 프래그먼트 셰이더는 렌더링 대상 픽셀 수가 많을수록 처리 부하가 커진다.
2.2 오버 드로우
렌더링을 할 때 대상 오브젝트의 투명도는 중요한 문제이다. 예를 들어 카메라에서 겹치는 오브젝트를 두개 만들었을 때
전방에 있는 오브젝트와 후방에 있는 오브젝트가 둘다 100% 불투명하다고 생각을 해보고 처리과정을 이야기 해보겠다.
이때는 앞에 오브젝트가 후방의 오브젝트를 가리기 떄문에 전방의 오브젝트만 렌더링이 진행된다. 이렇게 되면서
프래그먼트 셰이더 연산을 생략할 수 있다.
하지만 앞에 있는 오브젝트가 반투명인 경우 오버드로우가 발생한다.
이때는 뒤쪽에 있는 오브젝트를 렌더링하고 겹치는 부분은 색을 블랜딩하여 렌더링을 진행하여 추가적인 연산이 발생한다.
해당 부분도 최적화에서 중요하니 참고해야한다.
2.3 드로우콜, 셋 패스 콜
렌더링은 GPU 뿐만 아니라 CPU에도 많은 처리 부하가 생긴다.
위에 작성했던 것 처럼 CPU에서 GPU에게 명령을 내리는게 드로우 콜 이라고 하는데.
렌더링할 오브젝트 수만큼 실행이 된다. 이때 텍스처 등의 정보가 이전 드로우콜에서 그린 오브젝트의 텍스처와 다를 경우, 이를 GPU에서 설정하는 과정을 거친다. 이는 Set Pass Call이라고 하는데 비교적 무거운 작업이다.
이 과정은 CPU의 렌더 스레드에서 이루어져서 CPU의 처리 부하를 유발하고 너무 많으면 성능에 영향을 미친다.
2.4 배칭
유니티에서는 드로우 콜을 줄이기 위해 드로우콜 배칭이라는 구조가 존재한다.
이는 동일한 텍스처의 정보, 즉 동일한 마테리얼을 가진 오브젝트의 메시를 CPU측에서 미리 결합하여 한번의 드로우 콜로 그리는 방식이다.
런타임에 배치하는 다이나믹 배칭, 미리 결합된 메시를 생성해두는 정적 배치가 있다.
또한 Scriptable Render Pipeline 에는 SRP Batcher 라는 메커니즘이 구현되어 있는데
이를 사용하면 셰이더 변형이 동일하다면 메시나 마테리얼이 다르더라도 세트패스 호출을 한번을 묶을 수 있다.
드로우 콜은 줄어들지 않지만, 처리 부하가 큰 것은 셋 패스콜이라 이를 줄이기 위한 구조이다.
2.5 메시
3DCG에서는 3D 공간 위에 수많은 삼각형을 연결하여 입체적인 형상을 표현한다.
이 삼각형의 집합을 메쉬라고 한다.
'최적화' 카테고리의 다른 글
튜닝<그래픽> (1) | 2025.06.17 |
---|---|
튜닝 - 물리(Physics) (1) | 2025.06.15 |
에셋 관련 최적화 (1) | 2025.06.01 |
튜닝 기본 상식(2) (0) | 2025.05.17 |
유니티 프로젝트 튜닝 전, 중 주의사항 (0) | 2025.04.06 |