DirectX/DirectX 3D_(구)

21_Thread

컴맹학자 2021. 7. 28. 09:07
728x90

ThreadDemo.cpp, h

더보기
#include "stdafx.h"
#include "ThreadDemo.h"

void ThreadDemo::Initialize()
{
	//일반 반복문
	{
		//Loop();
	}
	//Thread
	{
		//MultiThread();
		//Mutex();
		//RacCondition();
		ExcuteTimer();
	}
}

void ThreadDemo::Update()
{
	progress += 0.1f;
	ImGui::ProgressBar(progress / 1000.0f );
}

void ThreadDemo::Loop()
{
	for (int i = 0; i < 100; i++)
		printf("Loop1 : %d\n", i);
	printf("Loop1 End\n");

	for (int i = 0; i < 100; i++)
		printf("Loop2 : %d\n", i);
	printf("Loop2 End\n");

}

void ThreadDemo::Loop1()
{
	for (int i = 0; i < 100; i++)
		printf("Loop1 : %d\n", i);
	printf("Loop1 End\n");
}

void ThreadDemo::Loop2()
{
	for (int i = 0; i < 100; i++)
		printf("Loop2 : %d\n", i);
	printf("Loop2 End\n");
}

void ThreadDemo::MultiThread()
{
	//C++ STL 방식
	thread t1(bind(&ThreadDemo::Loop1, this));
	thread t2(bind(&ThreadDemo::Loop2, this));
	
	//종료시점 알려줌 (제어순서를 정해줌)
	t2.join();
	printf("t2.join\n");
	t1.join();
	printf("t1.join\n");
}

void ThreadDemo::Mutex()
{
	//thread t(bind(&ThreadDemo::MultiThread, this));
	//람다함수
	thread t([&]() 
	{
		while (true)
		{
			Sleep(100);
			
			printf("%f\n", progress);

			if (progress >= 1000)
			{
				printf("Done!\n");
			}
			
				
		}
	});
	t.detach(); //쓰레드 안에 있는 함수가 끝나면 알아서 끝남
}

void ThreadDemo::Thread(int & count)
{
	for (int i = 0; i < 1e+6; i++)
	{
		m.lock();
		count++;
		m.unlock();
	}
}

void ThreadDemo::RacCondition()
{
	int count = 0;
	vector<thread> works;

	for (int i = 0; i < 4; i++)
	{
		function<void(int&)> f = bind(&ThreadDemo::Thread, this, placeholders::_1);
		works.push_back(thread(f, ref(count)));
	}
	for (int i = 0; i < 4; i++)
		works[i].join();

	printf("Count : %d\n", count);
}

void ThreadDemo::ExcuteTimer()
{
	//시간마다 호출할 함수 , 호출할 시간, 간격 (이벤트 기반)
	//repeater.Start(bind(&ThreadDemo::Repeater, this), 1000);
	//noRepeater.Start(bind(&ThreadDemo::NoRepeater, this), 2000 , 2);

	//위 내용을 람다 함수로 호출 하는 방법 (로딩 만들때 좋음)
	repeater.Start([]() {printf("1초마다 무한 호출\n"); }, 1000);
	noRepeater.Start([]() {printf("2초마다 2번 콜\n"); }, 2000, 2);
}

void ThreadDemo::NoRepeater()
{
	printf("2초마다 2번 콜\n");
}

void ThreadDemo::Repeater()
{
	printf("1초마다 무한 호출\n");
}

 

#pragma once
#include "Systems/IExecute.h"

class ThreadDemo : public IExecute
{
public:
	virtual void Initialize() override;
	virtual void Destroy() override {};
	virtual void Update() override;
	virtual void PreRender() override {};
	virtual void Render() override {};
	virtual void PostRender() override {};
	virtual void ResizeScreen() override {};

private:
	void Loop();

	void Loop1();
	void Loop2();
	void MultiThread();
		
	void Mutex();

	void Thread(int& count);
	void RacCondition();

	void ExcuteTimer();
	void NoRepeater();
	void Repeater();

private:
	float progress = 0.0f; // 제어용
	mutex m;

	Timer noRepeater;
	Timer repeater;
};

 


보충

더보기

1. 
 h/w : Program 밑에 있는 여러개(멀티) Process들을 말함 [병렬처리]
 s/w : 함수 단위를 각각의 Core에서 별개로 처리

 

위에 있는 그림과 같이 Visul Studio는 Program으로 그 밑에서 빨강색 박스로 묶인 것들이 Process


2. 

DX11에서 기존 파이프라인에서 Thread처리 하는데 거기서 추가로 Thread를 사용이 가능하고 사용 할 줄 알면 더욱더 효율적으로 계산이 됨 

3. 
Critical Section : 자원을 처리하는 공통 공간
Mutex : Critical Section에 임계구역을 걸어서 들어온 자원값이 처리 하기 전까지 접근 못하게 하고선 처리가 끝나면 풀어줌
Semaphore : 자원에 처리해야하는 번호를 매겨서 처리
DeadLock : Critical Section영역에 문제가 생겨서 다른 Thread가 접근 못하는 현상

 

4. 람다함수

기존에 void ...(); 형식으로 함수를 선언하고 .cpp 에서 정의를 한다면 람다 함수는 [](){} 형식으로 그때 필요한 함수를 인스턴스 마냥 만들어서 사용 하는 방법.

 

장점 : 코드의 간결성, 자연연산 수행, 병렬처리 가능(Thread)

단점 : 

1. 호출이 까다롭다

2. 일반 단순 반복문에서 사용하면 선능이 떨어짐

3. 불필요하게 사용하면 가독성이 떨어짐 (남이 보면 어려움)

 

더 자세한 내용은

https://modoocode.com/196


-> 알아야 하는 이유
Thread(GPU)영역 에서 값을 가져오는 방법을 알기 위해
병렬처리 과정을 이해 하기 위해

 

ModelEditor, UnitTest 아무대나 만들어서 실행

'DirectX > DirectX 3D_(구)' 카테고리의 다른 글

23_TextureBuffer (CS)  (0) 2021.07.29
22_RawBuffer (CS)  (0) 2021.07.28
20_ModelAnimation  (0) 2021.07.26
19_ModelMaterial [2/2]  (0) 2021.07.19
19_ModelMaterial [1/2]  (0) 2021.07.17