유니티의 멀티스레딩

kj0284
WeKlem
Published in
8 min readJun 22, 2023

--

안녕하세요 위클램의 박경준매니저입니다.

오늘은 유니티의 멀티스레드의 사용에 대해 알아보겠습니다.

멀티스레딩(MultiThreading)란?

멀티스레딩에 대해서 설명하려면 스레드에 대해서 알아야겠죠?

스레드(thread)는 직역하면 ‘실’을 의미해요.

의류를 만들 때 수 많은 실을 이용해서 옷을 만들듯이, 컴퓨터도 스레드라는 실이 모여 프로그램이라는 옷이 만들어진다고 표현할 수 있겠네요.

이 때, 옷이 만들어지는 과정을 컴퓨터에서는 프로세스로 비유할 수 있습니다.

즉, 프로세스는 “프로그램을 실행하는 과정”,
스레드는 “프로세스를 구성하는 작업 단위”라고 할 수 있습니다.

이 때, 프로세스를 구성하는 스레드가 하나라면 싱글스레드 환경이라고 하고, 여러 개라면 멀티스레딩이라고 합니다.

멀티스레딩의 장점

멀티스레딩은 어떤 장점을 가지고 있을까요?

앞서 “스레드는 프로세스를 구성하는 작업 단위”라고 말씀드렸어요.

여러 사람들이 게임을 만든다고 가정했을 때, 한 사람이 게임 전체를 만드는 것보다, 한 명은 이펙트, 한 명은 게임 시나리오, 한 명은 개발을 나눠 일을 하는 것이 효율이 더 좋겠죠?

유니티의 멀티스레딩은 물리코어 당 1개의 스레드를 만들어줘요.

물리코어?
컴퓨터에서 프로그램을 실행하는 일을 하는 일꾼이라 비유할 수 있습니다.

2개 이상의 물리코어를 가진 컴퓨터가 하나의 프로세스를 여러 스레드에게 일을 나눠서 시킨다면 성능이 향상되는 효과를 얻을 수 있어요.

멀티스레딩에서 발생할 수 있는 문제들

1. 경쟁 조건 (Race Condition)

독립된 두 작업이 동시에 같은 값을 사용하려 할 때 그들 사이의 경쟁에 의해 실행 결과를 예측할 수 없게 되는 것을 “경쟁” 이 발생한다고 해요.

이러한 문제는 멀티스레딩을 사용할 경우 발생할 수 있어요.

예를 들어,
A스레드는 a라는 숫자에 곱하기 2를 하는 일을 하고 있고,
B스레드는 a라는 숫자에 나누기 2를 하는 일을 하고 있어요.

두 일이 동시에 작동하고 있을 때 결과를 예측할 수 없겠죠?

멀티스레딩 환경은 각 스레드들이 병렬로 일들이 수행되기 때문에 이러한 경쟁 조건이 발생할 가능성이 있어요.

병렬이란?
여러 명의 일꾼동시에 각자의 일을 처리하는 것을 말해요.

2. 데드락(DeadLock)

네 개의 도로가 교차로에서 만나는 상황을 가정합니다. 각 도로는 교차로를 통과하기 위해 다른 도로와 교차하는 시점에서 신호등을 확인합니다.

만약 도로 A의 차량은 도로 B의 신호를 기다리고 있고, 도로 B의 차량은 도로 A의 신호를 기다리는 상황일 때

데드락의 예시

다음 그림과 같이 모든 자동차가 움직이지 못하고 멈춰버리는 상황이 발생합니다.

이처럼 서로 아무것도 하지 못하고 대기만 하고 있는 상황이 지속되는 것을 “데드락”이라고 합니다.

위의 예시처럼 멀티스레딩 환경에서 스레드들이 할 일들을 잘못 정해주면각 스레드들의 일이 꼬여서 아무것도 하지 못하는 데드락상황이 발생할 가능성이 있습니다.

3. 종속성 문제

여러 사람이 한 일을 나눠서 할 때 각각의 일들이 관련이 있을 경우 서로 소통을 하거나 순서에 맞게 일을 진행해야 하죠?

하지만 멀티스레딩 환경에서는 각 일들이 동시에 실행되고, 서로의 일이 연관이 있는지 스레드들은 모르기 때문에 문제가 발생할 수 있어요.

예를 들어, 저는 물 붓기-> 스프 넣기-> 사리 넣기 -> 계란 넣기 절차로 라면을 끓이는데 멀티스레딩 환경에서 이 작업을 컴퓨터에게 시키면 각 단계들을 순서대로 하지 않고 병렬로 작업을 하게 됩니다.

병렬로 라면끓이기를 진행하게 되면 어떤 단계가 먼저 끝날지 예측할 수 없습니다.

그렇다면 내가 원하는 맛있는 라면의 맛이 일정하게 나오지 않겠죠?

라면을 끓이는 단계들이 관련이 있는 것처럼 일들이 관계가 있는 것을
종속성을 가진다”라고 해요.

멀티스레딩을 사용할 때 종속성에 문제가 생기면 원하는 결과물이 나오지 않을 수 있어요.

유니티는 멀티스레딩을 어떻게 구현할까?

앞서 멀티스레딩의 장점과 단점에 대해 설명드렸습니다.

유니티는 멀티스레딩에서 발생할 수 있는 문제들을 예방하기 위해 Job시스템을 사용하고 있습니다.

Job 시스템이란?

Job 시스템을 설명하기 전에 Job 시스템에서 사용하는 용어에 대해 알아봅시다.

메인스레드:
— 게임이 시작될 때 자동으로 생성되는 스레드입니다.
— 게임의 주요 작업을 담당하며, 일을 시킬 스레드들을 생성하고 관리합니다.

워커 스레드(Worker Thread):
— 워커 스레드는 일들을 실제로 수행하는 스레드입니다.

스레드 풀(Thread Pool):
— 스레드 풀은 워커 스레드들의 집합입니다.
— 일이 들어오면 스레드 풀에서 사용 가능한 워커스레드에게 일을 시킵니다.

네이티브 컨테이너(Native Container):
— 네이티브 컨테이너는 워커스레드의 작업 결과를 저장하는 공간입니다.
— 네이티브 컨테이너는 작업 결과를 메모리에 저장하며, 다른 스레드에서 이 결과를 접근할 수 있도록 공유합니다.
— 이를 통해 작업 결과를 메인 스레드 등 다른 곳에서 확인하고 활용할 수 있습니다.

Job 시스템은 다음과 같은 방법으로 진행됩니다.

  1. Job 생성: 실행할 작업(Job)들을 생성합니다.
  2. 스레드 풀 생성: 일을 처리하는 스레드(워커스레드)들의 공간인 스레드 풀을 생성합니다.
  3. Job 스케줄링: Job들의 실행 순서를 결정합니다. 실행 순서가 결정되면 해당 일들을 워커스레드에게 줍니다.
  4. 작업 실행: 할당된 작업들은 워커스레드들에 의해 병렬로 실행됩니다. 각 워커스레드는 할당된 작업을 처리하고, 작업이 완료되면 다음 작업을 처리할 준비를 합니다.
  5. 작업 완료 및 결과 수집: 작업이 완료될 때마다 해당 작업의 결과를 종합하고, 정해진 다음 일들을 워커스레드에게 할당합니다.
  6. 작업 종료: 모든 일들이 완료되면 Job 시스템은 종료됩니다. 이후에는 스레드 풀을 해체하고 스레드들을 메모리에서 정리합니다. (메모리에서 할당을 해제합니다.)

Job 시스템의 장점

유니티의 Job 시스템은 다음과 같은 장점들을 가지고 있어요.

1. 하드웨어 성능을 잘 사용할 수 있게 도움

Job 시스템에서는 다음과 같은 기능들을 제공해요.

  • 컴퓨터의 물리 코어 수에 맞게 스레드를 생성한다.
  • 쉬고있는 워커스레드에 일을 자동으로 준다.

이러한 기능들을 Job시스템에서 제공하기 때문에 일일이 개발자가 스레드를 관리해야하는 수고를 줄여줄 수 있고, 코어가 많은 경우 좋은 성능을 제공할 수 있어요.

2. 멀티스레딩에서 발생할 수 있는 문제 예방

Job 시스템은 앞서 설명한 멀티스레딩으로 인해 발생할 수 있는 문제들을 예방할 수 있어요.

경쟁 조건 예방

Job 시스템은 메인스레드의 데이터를 사용할 때 데이터를 복사(깊은 복사)해서 사용해요.

깊은 복사(deep copy)란? :
복사할 데이터와 똑같은 독립된 데이터를 만드는 방법을 말해요.

이 방법은, 메인스레드에서 데이터와 충돌이 발생하지 않도록 하여, 경쟁 조건을 예방할 수 있습니다.

데드락 문제 예방

Job 시스템을 사용하여 일의 우선순위를 정하고 일들이 동일한 순서로 자원을 요청하도록 조정하면 데드락을 예방할 수 있습니다.

종속성 문제 해결

  1. Job시스템은 일의 우선 순위를 정하여 관련이 있는 일들을 원하는 순서대로 처리할 수 있게 할 수 있습니다.
  2. 워커 스레드에서 일을 처리한 후 결과 수집을 할 때 결과들을 네이티브 컨테이너라는 공간에 저장합니다.
    메인스레드는 네이티브 컨테이너에 접근이 가능해 일이 처리된 이후 결과들을 확인하여 동기화가 가능합니다.

Job System 어떻게 활용할까?

Job System은 주로 다음과 같은 상황에서 사용해요.

  • 그래픽 렌더링, 애니메이션, 물리 시뮬레이션 등 동시에 일어나야 하는 작업
  • 파일 불러오기, 네트워크 통신들과 같은 시간이 걸리는 작업

마무리

오늘은 유니티가 멀티스레드를 사용해 게임을 구현하는 방법에 대해 알아보았습니다.

멀티스레드에서 발생할 수 있는 문제점을 알고, 이를 Job 시스템을 통해 멀티스레딩으로 게임을 만든다면 더 성능이 좋은 게임을 만들 수 있을거에요.

이상으로 포스팅을 마치겠습니다

다들 LGTM(Looks Good To Me)하길 바래요🙂

자료출처 :

스레드 설명 : https://namu.wiki/w/%EC%8A%A4%EB%A0%88%EB%93%9C

스레드 풀 : https://en.wikipedia.org/wiki/Thread_pool

데드락과 경쟁상태 : https://velog.io/@mooh2jj/%EA%B5%90%EC%B0%A9%EC%83%81%ED%83%9CDeadlock%EC%9D%B4%EB%9E%80
https://namu.wiki/w/%EB%8D%B0%EB%93%9C%EB%9D%BD

Job 시스템 :
https://javart.tistory.com/m/135
https://everyday-devup.tistory.com/97

--

--