1์ฅ ๋ฉํฐ ์ค๋ ๋ฉ
6. ์๊ณ ์์ญ๊ณผ ๋ฎคํ ์ค
๊ฒฝ์ ์ํ๋ฅผ ํด๊ฒฐํ๋ ์ฌ๋ฌ ๋ฐฉ๋ฒ ์ค ํ๋๋
๋ค๋ฅธ ์ค๋ ๋๋ X๋ฅผ ๊ฑด๋๋ฆฌ๋ ค๊ณ ํ๋ฉด ํ์ฌ ์ค๋ ๋๊ฐ X๋ฅผ ๋ค ์ฌ์ฉํ ๋๊น์ง ๊ธฐ๋ค๋ฆฌ๋ ๊ฒ์ด๋ค.
์ด๋ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ฎคํ ์ค(mutex)์ด๋ค.
- ๋ฎคํ ์ค๋ ์ํธ ๋ฐฐ์ (mutual exclusion)์ ์ค์๋ง์ด๋ค.
- ๋ฎคํ ์ค๋ ๋ค๋ฅธ ๋ง๋ก ์๊ณ ์์ญ(critical section)์ด๋ผ๊ณ ๋ ํ๋ค.
C++์์ ๋ฎคํ ์ค๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ค์๊ณผ ๊ฐ๋ค.
- ์ค๋ ๋ 1์ด โก์์ ๋ฎคํ ์ค ์ฌ์ฉ๊ถ์ ์ป๋ ๋ฐ ์ฑ๊ณตํ๋ฉด โข์ผ๋ก ๋์ด๊ฐ๋ค.
- ๊ทธ๋ฌ๋ ๋ค๋ฅธ ์ค๋ ๋ 2๊ฐ ์ด๋ฏธ ๋ฎคํ ์ค ์ฌ์ฉ๊ถ์ ์ป์ ์ํ๋ฉด ์ค๋ ๋ 1์ ๋ ์ด์ ์งํํ์ง ๋ชปํ๊ณ ์ ์ง๋๋ค.
- ํํธ ์ค๋ ๋ 2๋ โข์ ์คํ ํ โฃ๋ฅผ ํต๊ณผํ๊ฒ ๋๋๋ฐ ๊ทธ์ ์ผ ์ค๋ ๋ 1์ ๋ฎคํ ์ค ์ฌ์ฉ๊ถ์ ์ป์ด ์คํ ์ง์ ์ด โข์ผ๋ก ๋์ด๊ฐ๋ค.
๊ทธ๋ฐ๋ฐ, ๋งค๋ฒ lock()๊ณผ unlock()์ ํธ์ถํ๋ ๊ฒ์ ๋ฒ๊ฑฐ๋ก์ธ ๋ฟ๋ง ์๋๋ผ ์์ธ ์ฒ๋ฆฌ ์ฝ๋ ์์ฑ๋ ์ด๋ ต๋ค.
โข์์ read()์ ์คํํ๋ค ์์ธ๋ฅผ ๋์ง๋ฉด ๋ค์ โข~โฃ ๊ณผ์ ์ ์คํ๋์ง ๋ชปํ๋ค. ์ด๋ฅผ ํด๊ฒฐํ๋ ค๋ฉด ์์ธ๊ฐ ๋ฐ์ํ๋๋ผ๋ unlock()์ ์คํํ ์ ์๊ฒ ํด์ผ ํ๋ค.
C++์ ๋ฎคํ ์ค ์ ๊ธ ์ํ๋ฅผ ๋ก์ปฌ ๋ณ์๋ก ์ ์ฅํ๊ณ ๊ทธ ๋ณ์๊ฐ ์ฌ๋ผ์ง ๋ ์๋์ผ๋ก ์ ๊ธ ํด์ ๊ฐ ๋๊ฒ ํ๋ lock_guard ํด๋์ค๋ฅผ ์ ๊ณตํ๋ค. ์ด ํด๋์ค๋ฅผ ์ฌ์ฉํ๋ฉด lock ๊ฐ์ฒด๊ฐ ์ฌ๋ผ์ง ๋ ์๋์ผ๋ก unlock()์ด ์คํ๋๋ค.
C#์์๋ ๋ณดํธํ๋ ค๋ ๋ณ์ ์์ฒด๋ฅผ ๋ฎคํ ์ค์ฒ๋ผ ์ฌ์ฉํ์ฌ ์ ๊ทธ๊ณ ๋ค ์ฐ๊ณ ๋๋ฉด ์ ๊ธ์ ํด์ ํ๋ค.
lock ๊ตฌ๋ฌธ ๋ธ๋ก์ ์ด์ฉํ๋ฉด ๋ณ๋์ unlock()์ ํธ์ถํ์ง ์์๋ ๊ตฌ๋ฌธ ๋ธ๋ก์ ๋๊ฐ ๋ ์๋์ผ๋ก ์ ๊ธ ํด์ ๊ฐ ๋๋ค.
C++ ๋ฉํฐ์ค๋ ๋ ๊ตฌํ ์ฝ๋ ์์ (์์ ๊ตฌํ๊ธฐ)
#include "stdafx.h"
#include <vector>
#include <iostream>
#include <chrono>
#include <thread>
#include <memory>
#include <mutex>
using namespace std;
const int MaxCount = 15000000;
const int ThreadCount = 4;
bool IsPrimeNumber(int number)
{
if (number == 1)
return false;
if (number == 2 || number == 3)
return true;
for (int i = 2; i < number - 1; i++)
{
if ((number % i) == 0)
return false;
}
return true;
}
void PrintNumbers(const vector<int>& primes)
{
for (int v : primes)
{
cout << v << endl;
}
}
int main()
{
// ๊ฐ ์ค๋ ๋๋ ์ฌ๊ธฐ์ ๊ฐ์ ๊บผ๋ด์จ๋ค.
int num = 1;
recursive_mutex num_mutex;
vector<int> primes;
recursive_mutex primes_mutex;
auto t0 = chrono::system_clock::now();
// ์๋ํ ์์ปค ์ค๋ ๋
vector<shared_ptr<thread> > threads;
for (int i = 0; i < ThreadCount; i++)
{
shared_ptr<thread> thread1(new thread([&]() {
// ๊ฐ ์ค๋ ๋์ ๋ฉ์ธ ํจ์.
// ๊ฐ์ ๊ฐ์ ธ์ฌ ์ ์์ผ๋ฉด ๋ฃจํ๋ฅผ ๋๋ค.
while (true)
{
int n;
{
lock_guard<recursive_mutex> num_lock(num_mutex);
n = num;
num++;
}
if (n >= MaxCount)
break;
if (IsPrimeNumber(n))
{
lock_guard<recursive_mutex> primes_lock(primes_mutex);
primes.push_back(n);
}
}
}));
// ์ค๋ ๋ ๊ฐ์ฒด๋ฅผ ์ผ๋จ ๊ฐ๊ณ ์๋๋ค.
threads.push_back(thread1);
}
// ๋ชจ๋ ์ค๋ ๋๊ฐ ์ผ์ ๋ง์น ๋๊น์ง ๊ธฐ๋ค๋ฆฐ๋ค.
for (auto thread : threads)
{
thread->join();
}
// ๋
auto t1 = chrono::system_clock::now();
auto duration = chrono::duration_cast<chrono::milliseconds>(t1 - t0).count();
cout << "Took " << duration << " milliseconds." << endl;
//PrintNumbers(primes);
return 0;
}
์ ๋ฉํฐ์ค๋ ๋ ๊ตฌํ ์์ ๋ฅผ ์คํํด๋ณด๋ฉด ์ค๋ ๋๊ฐ ํ๋์ผ ๊ฒฝ์ฐ ์คํ ์๊ฐ์ด 3900๋ฐ๋ฆฌ ์ด ์ ๋์ธ๋ฐ, ์ค๋ ๋๊ฐ 4๊ฐ์ผ ๋๋ 1300๋ฐ๋ฆฌ ์ด๊ฐ ๋์จ๋ค. ์ด๋ก ์ ์ผ๋ก 4๋ฐฐ๊ฐ ๋นจ๋ผ์ ธ์ผ ํ ๊ฒ ๊ฐ์๋ฐ ์ 3๋ฐฐ ๋ฐ์ ๋นจ๋ผ์ง์ง ์์์๊น?
- lock์ ๊ฑธ๋ ค ๋ค๋ฅธ ์ค๋ ๋๊ฐ ๋๊ธฐ ์ํ๋ก ์ ํํ๋ ์ํฉ์ด ๋ฐ์ํ๋ค.
- CPU๋ ๋ฉ๋ชจ๋ฆฌ ์ก์ธ์ค ์๊ฐ์ด ๊ธธ๋ค. ๋ฉํฐ์ค๋ ๋๊ฐ ์๋ํ๋ค ํ๋๋ผ๋ ๋ฉ๋ชจ๋ฆฌ์ ์ ๊ทผํ๋ ๋์์๋ CPU ๊ฐ์๋ณด๋ค ๋ ์ ์ ์์ CPU๋ฅผ ์ฒ๋ฆฌํ๊ฒ ๋๋ค.
์์ ๊ฐ์ ์ํฉ์ ํด๊ฒฐํ๊ธฐ ์ํด ๋ฎคํ ์ค๋ฅผ ์ต๋ํ ๋๋๋ฉด ์ด๋ป๊ฒ ๋ ๊น?
- ๋ฎคํ ์ค๋ฅผ ์ก์ธ์ค ํ๋ ๊ณผ์ ์ด ๋ฌด๊ฒ๊ธฐ ๋๋ฌธ์ ์คํ๋ ค ํ๋ก๊ทธ๋จ ์ฑ๋ฅ์ด ๋จ์ด์ง๊ฒ ๋๋ค.
- ๊ต์ฐฉ ์ํ๊ฐ ์ฝ๊ฒ ๋ฐ์ํ๋ค.
ํนํ ๋ ๋ฒ์งธ ๋ฌธ์ ๋ ์ฌ๊ฐํ๊ธฐ ๋๋ฌธ์ ๋ฎคํ ์ค๋ ์ด๋ ์ ๋ ๊ตต์งํ๊ฒ ์ ๊ธ ๋ฒ์๋ฅผ ์ก์์ผ ํ๋ค.
๋ฐ๋๋ก ๋ฎคํ ์ค๊ฐ ๋ณดํธํ๋ ์์ญ์ด ๋๋ฌด ๋์ผ๋ฉด ์ค๋ ๋๊ฐ ์ฌ๋ฟ์ด๋ผ ํ๋๋ผ๋ ํ๋์ผ ๋์ ๋ณ๋ฐ ์ฐจ์ด๊ฐ ์์ด์ง๋ค.
๋ฐ๋ผ์ ๋์์ ์ฐ์ฐํ๋ฉด ์ ๋ฆฌํ ๋ถ๋ถ์ ์ ๊ธ ๋จ์๋ก ๋๋๊ณ ๋ณ๋ ฌ๋ก ํ์ง ์์๋ ์ฑ๋ฅ์ ์ํฅ์ ์ฃผ์ง ์๋ ๋ถ๋ถ๋ค์ ์ ๊ธ ๋จ์๋ฅผ ๋๋์ง ์๋ ๊ฒ์ด ์ข๋ค.
7. ๊ต์ฐฉ ์ํ
๋ฉํฐ์ค๋ ๋ ํ๋ก๊ทธ๋๋ฐ์์ ๊ต์ฐฉ ์ํ๋ ๋ ์ค๋ ๋๊ฐ ์๋ก๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ ์ํฉ์ ์๋ฏธํ๋ค.
์ด๋ฌํ ๊ฒฝ์ฐ ๋ ์ค๋ ๋๋ ์์ํ ๋ฉ์ถฐ ์๊ฒ ๋๋ค.
๋ฎคํ ์ค๊ฐ ์ฌ๋ฟ์ผ ๋ ๊ต์ฐฉ ์ํ๋ฅผ ์ผ์ผํค์ง ์๋๋ก ํ๊ธฐ ์ํด ์ ๊ธ ์์์ ๊ท์น์ ๋ง๋ค์ด์ผ ํ๋ค.
8. ์ ๊ธ ์์์ ๊ท์น
๊ต์ฐฉ ์ํ๋ฅผ ์๋ฐฉํ๋ ค๋ฉด
- ๊ฐ ๋ฎคํ ์ค์ ์ ๊ธ ์์๋ฅผ ๋จผ์ ๊ทธ๋ํ๋ก ๊ทธ๋ฆฐ๋ค.
- ์ ๊ธ์ ํ ๋๋ ์ ๊ธ ์์ ๊ทธ๋ํ๋ฅผ ๋ณด๋ฉด์ ๊ฑฐ๊พธ๋ก ์ ๊ทผ ๊ฒ์ด ์๋์ง ์ฒดํฌํด์ผ ํ๋ค.
- ์ ๊ธ์ ํด์ ํ๋ ์์๋ ๊ต์ฐฉ ์ํ์ ์ํฅ์ ์ฃผ์ง ์๋๋ค.
์๋ฅผ ๋ค์ด ๋ฎคํ ์ค A, B, C๊ฐ ์๋ค๊ณ ๊ฐ์ ํ์ ๋, ์ด๋ค์ ์ ๊ธ ์์๋ A->B->C์ด๋ค.
์๋ ์ํฉ์ ๋์ผํ ์์๋ก ์ ๊ฐ๊ธฐ ๋๋ฌธ์ ๊ต์ฐฉ ์ํ๋ฅผ ์ผ์ผํค์ง ์๋๋ค.
๋ฎคํ ์ค ํ๋๋ง ์ ๊ทธ๋ ๊ฒ๋ ์์ ํ๋ค.
๋ฐ๋ ์์๋ก ์ ๊ทธ๋ฉด ๊ทธ์ ์ผ ๊ต์ฐฉ ์ํ๋ฅผ ์ผ์ผํจ๋ค.
์ด๋ ๋ฎคํ ์ค๋ ์ฌ๊ท์ฑ์ ๊ฐ์ง๋ ๊ฒ๊ณผ ๊ฐ์ง์ง ์๋ ๊ฒ์ด ์๋ค.
์ฌ๊ท ๋ฎคํ ์ค๋ ํ ์ค๋ ๋๊ฐ ๋ฎคํ ์ค๋ฅผ ์ฌ๋ฌ ๋ฒ ๋ฐ๋ณตํด์ ์ ๊ทธ๋ ๊ฒ์ ํ๋ฝํ๋ค.
์ฌ๋ฌ ๋ฒ ์ ๊ธ์๋ก ๊ทธ๋งํผ ์ ๊ธ ํด์ ๊ฐ ํ์ํ๋ค.
- ์ฒซ ์ ๊ธ์์ ์์๋ฅผ ์ด๊ธด๋ค๋ฉด ๊ต์ฐฉ ์ํ๋ฅผ ์ผ์ผํจ๋ค.
- ์ด๋ฏธ ์ ๊ทผ ๊ฒ์ ๋ํ ์ฌ๊ท ์ ๊ธ์ ์ ๊ธ ์์ ๊ทธ๋ํ์ ์๊ด์๋ค.
9. ๋ณ๋ ฌ์ฑ๊ณผ ์๋ฆฌ์ผ ๋ณ๋ชฉ
- ์ฌ๋ฌ CPU๊ฐ ๊ฐ ์ค๋ ๋์ ์ฐ์ฐ์ ์คํํ์ฌ ๋์ ์ฒ๋ฆฌ๋์ ์ฌ๋ฆฌ๋ ๊ฒ์ ๋ณ๋ ฌ์ฑ์ด๋ผ ํ๋ค.
- ๋ณ๋ ฌ์ฑ์ด ์ ๋๋ก ๋์ค์ง ์๋ ๊ฒ, ์ฆ ๋ณ๋ ฌ๋ก ์คํ๋๊ฒ ํ๋ก๊ทธ๋จ์ ๋ง๋ค์๋๋ฐ ์ ์ ํ CPU๋ง ์ฐ์ฐ์ ์ํํ๋ ํ์์ ์๋ฆฌ์ผ ๋ณ๋ชฉ์ด๋ผ ํ๋ค.
๋ฎคํ ์ค๋ก ์ ๊ทผ ๊ตฌ๊ฐ์ ๋ค๋ฅธ ์ค๋ ๋๊ฐ ์คํํ๋ ค ํ๋ฉด ๊ทธ ์ค๋ ๋๋ ์ผ์ ์ ์ง๊ฐ ๋๋ค. ๋ฐ๋ผ์ ๊ทน๋จ์ ์ธ ๊ฒฝ์ฐ ์ฌ๋ฌ CPU๊ฐ ๋ณ๋ ฌ ์ฒ๋ฆฌ๋ฅผ ํ๋๋ผ๋ ์ค์ ๋ก๋ CPU 1๊ฐ๋ฅผ ์ ์ธํ๊ณ ๋๋จธ์ง CPU์๋ ๋ ธ๋ ๊ตฌ๊ฐ์ด ์๊ธฐ๊ฒ ๋๋ค.
CPU ๊ฐ์๊ฐ ๋ง์์ง์๋ก ๋น ๊ณต๊ฐ์ ๋์ด์ง๋ค. ๋ณ๋ ฌ๋ก ์ฒ๋ฆฌํ ์ ์๋ ๊ตฌ๊ฐ, ์ฆ ์๋ฆฌ์ผ ๋ณ๋ชฉ์ด ์กด์ฌํ๋ ์๊ฐ์ด ๊ธธ์ด์ง์๋ก ์ด ์ฒ๋ฆฌ๋์ ์ค์ด๋ค๊ฒ ๋๋ค. ์ด์ฒ๋ผ ์๋ฆฌ์ผ ๋ณ๋ชฉ์ด ์์ ๋, CPU๊ฐ ๋ง์์๋ก ์ด ์ฒ๋ฆฌ ํจ์จ์ฑ์ด ๋จ์ด์ง๋ ํ์์ ์๋ฌ์ ๋ฒ์น ํน์ ์๋ฌ์ ์ ์ฃผ๋ผ๊ณ ํ๋ค.
์๋ฌ์ ์ ์ฃผ๋ฅผ ์ค์ด๋ ค๋ฉด ์๋ฆฌ์ผ ๋ณ๋ชฉ์ด ๋ฐ์ํ๋ ๊ตฌ๊ฐ์ ์ต์๋ก ์ค์ฌ์ผ ํ๋ค.
VS์ Concurrency Visualizer๋ ๋ฉํฐ์ค๋ ๋ ํ๋ก๊ทธ๋จ์ด ์ฌ๋ฌ ๊ฐ์ง ์ผ์ ์ ๋ง๋ก ์ ์ํํ๋์ง ๋ถ์ํ์ฌ ์ด๋ฅผ ์๊ฐํํด์ ๋ณด์ฌ์ฃผ๋ ๋๊ตฌ์ด๋ค. ์ด ๋๊ตฌ๋ฅผ ํ์ฉํ๋ฉด ์ฑ๋ฅ์ ๋ณ๋ชฉ์ ์ฝ๊ฒ ์ฐพ์๋ผ ์ ์๋ค.
- ๋๋ฒ๊ฑฐ ์์ด ํ๋ก๊ทธ๋จ ์คํ ํ Analyze > Concurrency Visualizer > Attach to Process ๋ก ๋ถ์์ ์์ํ๋ค.
- ๋ถ์์ ์์ํ๊ณ ๋ช ์ด ํ ์ค์ง ๋ฒํผ์ ๋๋ฅด๊ณ ์๋ก์ด ์ฐฝ์ด ๋จ๋ฉด โ ์ ๋๋ฅธ๋ค.
- โก๋ ๊ฐ ์ค๋ ๋๊ฐ ๋ฌด์จ ์ผ์ ํ๋์ง ๊ทธ๋ํ๋ก ๋ณด์ฌ์ค๋ค.
- โข์ ํด๋น ๊ตฌ๊ฐ ๋์ ๊ฐ ์ค๋ ๋๊ฐ ํ ์ผ์ ํต๊ณ๋ฅผ ๋ณด์ฌ์ค๋ค.
- 94%๊ฐ Execution์ด๋ ์๋ฏธ๋ ์ผํ ์๊ฐ์ 94%๊ฐ CPU ์ฐ์ฐ์ ํ๊ณ ์๋ค๋ ๊ฒ์ผ๋ก ๋งค์ฐ ์ํธํ ์ํ์ด๋ค.
- Synchronization์ด๋ ๋ฎคํ ์ค๋ฅผ ์ด๋ฏธ ๋ค๋ฅธ ์ค๋ ๋๋ก ์ ๊ทผ ์ํ๋ผ ๊ธฐ๋ค๋ฆฌ๋ ๋์์ ์๊ฐ์ ์๋ฏธํ๋ค.
- โฃ๋ ์ค๋ ๋ 4๊ฐ๊ฐ ๊ฐ๊ฐ ๋ฌด์์ ํ๋์ง ๋ณด์ฌ์ค๋ค.
๋ค์์ผ๋ก ๋ณ๋ ฌ ๋ณ๋ชฉ์ด ๋ฐ์ํ๋ ํํ ๊ฒฝ์ฐ๋ฅผ ์์๋ณด์.
๋จผ์ ๋๋ฐ์ด์ค ํ์๊ณผ CPU ํ์์ ์์์ผ ํ๋๋ฐ, ๋๋ฐ์ด์ค ํ์์ ๊ธฐ๊ธฐ์ ์๋ ์ฅ์น์ ๋ญ๊ฐ๋ฅผ ์์ฒญํด์ ๊ฒฐ๊ณผ๊ฐ ์ฌ ๋๊น์ง ๊ธฐ๋ค๋ฆฌ๋ ์๊ฐ์ ์๋ฏธํ๋ค. ์ด๋ ์ค๋ ๋๋ ์ ์๋ ์ํ์ด๋ฏ๋ก ๋๋ฐ์ด์ค ํ์ ๋์์๋ CPU๊ฐ ์ฐ์ฐ์ ํ์ง ์๊ณ ์๊ธฐ ๋๋ฌธ์ ์๊ฐ์ด ๋ญ๋น๋๋ค. ๋ฐ๋ผ์ ๋ค๋ฅธ ์ค๋ ๋๋ฅผ ์ํ CPU ์ฐ์ฐ์ ํ๋ ๊ฒ์ด ํจ์จ์ ์ด๋ค.
๋๋ฐ์ด์ค ํ์ ๋์(ReadFromDisk)์๋ ๋ฎคํ ์ค ์ ๊ธ์ ํ์ง ์๋๋ค. ๋จ, ๋๋ฐ์ด์ค ํ์ ๋์ X๊ฐ ๋ณ๊ฒฝ๋์์ ๊ฐ๋ฅ์ฑ์ด ์์ผ๋ ๋ฎคํ ์ค ์ ๊ธ ํ A์ ์ํ ์ฒดํฌ๋ฅผ ๋ค์ ํด์ผ ํ๋ค.