KoreanFoodie's Study
[C++ 게임 서버] 1-24. 연습문제 (소수의 갯수 구하기) 본문
[C++ 게임 서버] 1-24. 연습문제 (소수의 갯수 구하기)
핵심 :
1. 연습문제를 풀어보자... (주어진 숫자까지의 소수의 갯수 구하기)
2. 쓰레드 혹은, future 를 통해 구현할 수 있다.
3. thread::hardware_concurrency() 를 이용해, 실제 코어 갯수만큼 쓰레드를 생성하는 것이 더 효율적일 수 있다(그보다 훨씬 많이 생성하는 것보다).
이제 연습문제를 풀어보자. 주어진 숫자에 대해, 1부터 해당 숫자까지 소수의 갯수를 구하는 문제이다.
일단 멀티 쓰레드를 이용할 것이니, 각 쓰레드에 태워 보낼 함수를 다음과 같이 정의하자 :
bool IsPrime(int InInput)
{
if (InInput <= 1)
return false;
for (int i = 2; i < int(sqrt(InInput))+ 1; ++i)
{
if (InInput % i == 0)
{
return false;
}
}
return true;
}
int CalculatePrime(int InStart, int InEnd)
{
int sum = 0;
for (int i = InStart; i <= InEnd; ++i)
{
if (IsPrime(i))
{
++sum;
}
}
return sum;
}
이제 main 함수에서 위 함수들을 사용할 것이다. 두 가지 방법이 있는데, 일단 강의에서는 아래 방식을 제시한다 :
int main()
{
const int MAX_NUMBER = 1'000'000;
vector<thread> threads;
int coreCount = thread::hardware_concurrency();
int jobCount = (MAX_NUMBER / coreCount) + 1;
atomic<int> primeCount = 0;
for (int i = 0; i < coreCount; ++i)
{
int start = (i * jobCount) + 1;
int end = min(MAX_NUMBER, (i+1) * jobCount);
threads.push_back(thread([start, end, &primeCount]()
{
primeCount += CalculatePrime(start, end);
}));
}
for (auto& t : threads)
{
t.join();
}
cout << "The number of Prime for " << MAX_NUMBER << " : " << primeCount << endl;
}
하지만 간단한 계산의 경우, future 를 사용하는 것이 더 간단할 때도 있다.
future 를 사용하면 다음과 같이 표현할 수 있다!
int main()
{
const int MAX_NUMBER = 1'000000;
const int MAX_THREAD = thread::hardware_concurrency();
int stepVal = MAX_NUMBER / MAX_THREAD;
// 무식하게 100등분하기
int sum = 0;
std::vector<shared_future<int>> futureVec;
for (int i = 1; i <= MAX_THREAD; ++i)
{
shared_future<int> f =std::async(std::launch::async ,CalculatePrime, stepVal * (i-1), stepVal * i);
futureVec.push_back(f);
}
if (stepVal * MAX_THREAD < MAX_NUMBER)
{
sum += CalculatePrime(stepVal * MAX_THREAD + 1, MAX_NUMBER);
}
// shared_future 을 이용하면 vector 를 이용해서 계산 가능 + for_each 로 안전하게 복사 없이 사용
// 그냥 future 을 사용하면 오류 발생 "삭제된 함수를 참조하려고 합니다"
for (shared_future<int>& f : futureVec)
{
sum += f.get();
}
// algo:: 네임스페이스를 이용한 계산
//for_each(futureVec.begin(), futureVec.end(), [&sum](shared_future<int> f) { sum += f.get(); });
cout << "The number of Prime+1 for " << MAX_NUMBER << " : " << sum << endl;
}
두 경우, 모두 다음과 같이 결과가 동일하게 나온다!
물론, 뒤의 그룹이 숫자가 더 커서 부하가 더 크겠지만... 일단 그런 건 넘어가도록 하자 😅
그렇다면 속도는 어떨까?
첫번째 녀석의 경우, 10'000'000 에 대해, 다음만큼 걸렸다 :
두번째 녀석의 경우, 10'000'000 에 대해, 다음만큼 걸렸다 :
future 보다, 그냥 쓰레드를 생성해서 하는 편이 더 빨랐다 😅
아무래도 쓰레드를 그냥 생성하는 것이 훨씬 가벼운 것이 아닌가 싶다!
'Game Dev > Game Server' 카테고리의 다른 글
[C++ 게임 서버] 2-2. 스마트 포인터 (0) | 2023.08.23 |
---|---|
[C++ 게임 서버] 2-1. Reference Counting (0) | 2023.08.21 |
[C++ 게임 서버] 1-23. DeadLock 탐지 (0) | 2023.08.08 |
[C++ 게임 서버] 1-22. Reader-Writer Lock (0) | 2023.08.07 |
[C++ 게임 서버] 1-21. ThreadManager (0) | 2023.07.27 |
Comments