태크놀로지

멀티쓰레드 프로그래밍으로 덧셈프로그램 만들기 (이외 방법) 본문

멀티코어

멀티쓰레드 프로그래밍으로 덧셈프로그램 만들기 (이외 방법)

원택 2020. 9. 13. 21:03

멀티쓰레드 프로그래밍으로 덧셈프로그램 만들기:1-taek-gameprogramming.tistory.com/27?category=889762

 

멀티쓰레드 프로그래밍으로 덧셈프로그램 만들기

한국산업기술대학교 게임공학부 정내훈 교수님 멀티코어 2주차 강의 멀티쓰레드 프로그래밍에서 중요한사항 올바른 결과가 나와야한다. 싱글 쓰레드보다 성능향상이 커야한다. 실습1 - 여러 쓰

1-taek-gameprogramming.tistory.com

이전 포스팅에서 로컬변수를 사용하여 멀티쓰레드  프로그래밍으로 덧셈프로그램을 만들었었다. 로컬 변수를 사용하지 않는 다른 방법이 있을까?

-> 각 쓰레드마다 변수들을 만들어서 쓰레드 종료 후 값들을 더해보자.

 

방법에 대한 문제발생

  • 쓰레드가 종료하는가?
  • Cache Trashing
    •  Invalidation PingPong
const int MAX_THREAD = 16;
volatile int sum[MAX_THREAD];

void f(int t_id, int num_thread)
{
	// 성능측정을 위해 volatile 사용
	volatile int local_sum = 0;
	for (int i = 0; i < 5000'0000 / num_thread; ++i)
	{
		sum[t_id] += 2;
	}
	//sum_lock.lock();
	//sum += local_sum;
	//sum_lock.unlock();
}

sum을 쓰레드 개수만큼 두어 각각 다른 곳에서 계산을 하여 Data Race는 발생하지 않는다.

 

결과확인

첫번째 컴파일
두번째 컴파일

성능향상이 있긴한데, 매 디버깅마다 성능이 중구난방

쓰레드 생성소멸 오버헤드가 큼 (알고리즘이 끝날때마다 쓰레드를 생성 소멸시), 따라서 게임에서 프로그램이 시작부터 끝날때까지 계속 쓰레드가 살아있어야한다.

 

Cache Trashing이란?

연산할때 캐시에 올라온 메모리를 읽어서 연산한다. 이때

한국산업기술대학교 멀티코어프로그래밍 정내훈 교수님 수업 ppt 참고

캐시는 int(Byte)단위가 아닌 캐시라인 단위로(블럭단위)로 읽는다. 우리가 사용하는 캐시는 64비트이기 때문에 64비트씩 읽어낸다.

L2캐시에서 연산을 위해 L3캐시에서 값을 불러오는데, L3캐시의 데이터 값이 최신값이 아니라면 다른코어의 L2캐시에게 업데이트를 해달라고 요청을 한다. 그럼 다른 코어에서 수정된 최신값을 L3캐시에 업데이트하는데 이러한 현상이 계속해서 발생하게 되면서 더 느려지게 된다. ( 하드웨어 상의 Data Race )

 

해결책

const int MAX_THREAD = 16;

volatile int sum[MAX_THREAD* 64];
mutex sum_lock;

void f(int t_id, int num_thread)
{
	// 성능측정을 위해 volatile 사용
	volatile int local_sum = 0;
	for (int i = 0; i < 5000'0000 / num_thread; ++i)
	{
		sum[t_id * 64] += 2;
	}
	//sum_lock.lock();
	//sum += local_sum;
	//sum_lock.unlock();
}

각 sum들을 다른 캐시에 저장한다. ( 64비트만큼 띄어서 저장한다. )

 

컴파일 결과

제대로 된 결과와 향상된 성능이 나온다.

 

현재 포스팅까지의 최종 정리

  • 병렬 컴퓨팅이란 무엇인가?
    • 프로그램의 속도를 실행 유닛을 많이두어서 늘리는것 (하드웨어, 컨텍스트, 쓰레드)
  • 쓰레드란 무엇인가?
    • 프로세스안에 실행의 흐름 (컨텍스트를 여러개 두는것, 컨텍스트는 쓰레드)
    • 같은 프로세스 안에 쓰레드는 스택이외에 데이터, 힙, 코드 영역을 공통으로 가진다.
  • 왜 멀티쓰레드 프로그래밍을 해야하는가?
    • 멀티코어에 최적화된 하드웨어를 활용할 수 없다.
    • 현재 하드웨어와 운영체제의 병렬처리 api는 멀티쓰레드 api이다.
  • 멀티쓰레드 프로그래밍은 어떻게 하는가?
    • C++11 표준 라이브러리 사용
  • 멀티쓰레드 프로그래밍의 어려움
    • Data Race, 성능 (올바른 결과가 나와야하고, 싱글쓰레드보다 성능향상이 필수여야한다는점이 어려움)
    • 예측할 수 없는 디버깅 결과

출처

한국산업기술대학교 게임공학부 정내훈 교수님 강의 - 멀티코어 프로그래밍