- CPU ์ฃผ์์
: ์ ๋ฒ ์๊ฐ ์ํธ ๋ฐฐ์ ์ ์ด์ด ๋ฉ๋ชจ๋ฆฌ ์ผ๊ด์ฑ ๋ฌธ์ ๋ ๊ณ ๋ คํด์ผ ํจ
: ์ง๊ธ๊น์ง ํ๋ก๊ทธ๋จ์ ๊ณต์ ๋ฉ๋ชจ๋ฆฌ์ ๋ํ ์ ๊ทผ(์ฝ๊ธฐ/์ฐ๊ธฐ)์ atomicํ๋ค๊ณ ๊ฐ์ ํจ
→ ์ปดํ์ผ๋ฌ๊ฐ ์ ๋๋ก ๊ธฐ๊ณ์ด๋ก ๋ฒ์ญํ๋ค๋ฉด
→ atomic : ๋ฉ๋ชจ๋ฆฌ์ ์ ๊ทผ์ด ์๊ฐ์ ์ผ๋ก ํํด์ง๋ฉฐ, ์๋ก ๊ฒน์น์ง ์๊ณ ์คํ ๊ฒฐ๊ณผ ์์๊ฐ ์ ํด์ง๋ฉด, ๋ชจ๋ ์ฐ๋ ๋์์ ๊ฐ์ ์์๋ก ๋ณด์
→ ๊ทธ๋ฌ๋ PC์์์ ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ์ atomic์ด ์๋ (๋ฉ๋ชจ๋ฆฌ์ ์ด ์์๋๋ก ๋ฉ๋ชจ๋ฆฌ์ ๋ด์ฉ์ด ๊ด์ธก๋์ง ์์)
: 0๋ฒ ์ฐ๋ ๋๋ false๋ฅผ ์ฝ๊ณ 1๋ฒ๋ false๋ฅผ ์ฝ์
: ์ ๋ฒ ์๊ฐ์ ํ๋ ํผํฐ์จ ์๊ณ ๋ฆฌ์ฆ์์ std::atomic_thread_fence(std::memory_order_seq_cst)๋ฅผ ์ ์ธํ ๊ฒฝ์ฐ ์๋์ ๊ฒฐ๊ณผ์ฒ๋ผ ์ํธ ๋ฐฐ์ ๊ฐ ๊นจ์ง
→ ์ปดํ์ผ ๋ฌธ์ ์์. ๋ฉ๋ชจ๋ฆฌ ๋ฌธ์ . ์์๋๋ก ์์ฝ์ (atomicํ์ง ์๋ค, volatile๋ก ํด๊ฒฐ๋์ง ์์ - CPU์ ์๊ด์์)
→ 99.995% atomicํ์ง๋ง, 0.005%์ ๋๋ atomic์ด ์๋ (CPU ๋ชจ๋ธ์ ๋ฐ๋ผ ์์น๋ ๋ค๋ฆ)
: ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ์ด atomicํ์ง ์์ ์ด์ → CPU ์ฌ๊ธฐ
1) Line Based Cache Sharing (๋ผ์ธ ๊ธฐ๋ฐ ์บ์ ๊ณต์ ) : ํ๋์ CPU๊ฐ ๋ฉ๋ชจ๋ฆฌ์ ์ฐ๊ธฐ๋ฅผ ์ํํ๋ฉด ๋ค๋ฅธ CPU๊ฐ ๋์ผํ ์บ์ ๋ผ์ธ์ ๊ฐ์ง ์บ์์ ๋ด์ฉ์ ๋ฌดํจํ ํ ๊ฐ๋ฅ์ฑ ์กด์ฌ
2) Out of order (๋ช ๋ น์ด ์์ ๋ณ๊ฒฝ) : ์ฐ์ ์ ์ผ๋ก ์คํํ ์ ์๋ ๊ฒ๋ค์ ๋ฏธ๋ฆฌ ํด๋ฒ๋ฆผ
๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ์ด ์๊ฐ์ X, ๋ฉํฐ์ฝ์ด์์ ์ ์ฝ์ด์ Out of order์ด ๊ด์ธก๋จ
3) write buffering (์ฐ๊ธฐ ๋ฒํผ๋ง)
→ ์ฌ๊ธฐ ์์น๋ฉด ์คํ ์๋ ๋๋ฆผ
→ CPU๋ ํ๋ก๊ทธ๋จ์ ์์ฐจ์ ์ผ๋ก ์คํํ๋ ์ฒ๋ง ํจ (์ด๋ฅผ ๋์์ฃผ๋ ํน์ํ HW ์กด์ฌ)
const auto SIZE = 50000000;
volatile int x, y;
int trace_x[SIZE], trace_y[SIZE];
void ThreadFunc0()
{
for (int i = 0; i < SIZE; i++) {
x = i;
// atomic_thread_fence(std::memory_oreder_seq_cst);
trace_y[i] = y;
}
}
void ThreadFunc1()
{
for (int i = 0; i < SIZE; i++) {
y = i;
// atomic_thread_fence(std::memory_oreder_seq_cst);
trace_x[i] = x;
}
}
int main()
{
std::thread t0{ ThreadFunc0 };
std::thread t1{ ThreadFunc1 };
t0.join();
t1.join();
int count = 0;
for (int i = 0; i < SIZE; ++i)
if (trace_x[i] == trace_x[i + 1])
if (trace_y[trace_x[i]] == trace_y[trace_x[i] + 1]) {
if (trace_y[trace_x[i]] != i) continue;
count++;
}
cout << "Total Memory Inconsistency: " << count << endl;
}
: x, y - ์ฐ๋ ๋ ๊ฐ ๊ณต์ ๋๋ ๋ณ์
: trace_x[SIZE], trace_y[SIZE] - ์ฐ๋ ๋์์ ๋ฐ์ํ ๊ฐ๋ค์ ๊ธฐ๋กํ ๋ฐฐ์ด
: ์๋ก ๋ค๋ฅธ ์ฐ๋ ๋์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ฝ๊ณ ์ฐ๊ณ ์๋ค.
: count - ์ผ๊ด์ฑ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ํ์๋ฅผ ์ ์ฅํ ๋ณ์
: if (trace_y[trace_x[i]] == trace_y[trace_x[i] + 1]) - ํด๋น ๊ฐ์ ๋์ํ๋ trace_y ๊ฐ๋ ๊ฐ๋ค๋ฉด count ++
: if (trace_y[trace_x[i]] != i) continue; - ์ด์ ์ธ๋ฑ์ค์ ๋ค๋ฅธ ๊ฐ์ด๋ผ๋ฉด ์นด์ดํธ ํ์ง ์๊ณ ๋ค์์ผ๋ก ๋์ด๊ฐ
: ์ฃผ์์ ํ๋ฉด ๊ฒฐ๊ณผ๋ 0์ผ๋ก ๋์จ๋ค. atomic<int>๋ฅผ ์ฌ์ฉํด๋ ๊ฒฐ๊ณผ๊ฐ 0์ด๋ ์๋๊ฐ ๋งค์ฐ ์ ํ๋จ.
- ๋ฉ๋ชจ๋ฆฌ ์ผ๊ด์ฑ
1) = ๋ฌด๋ชจ์์ฑ(Consistency) - ๋ฉ๋ชจ๋ฆฌ๊ฐ ์์๋๋ก ์งํX,
2) ๊ฐํ ๋ชจ๋ธ๊ณผ ์ฝํ ๋ชจ๋ธ์ด ์๊ณ ๊ฐ๊ฐ ํ์ฉ๋๋ ๊ฒฐ๊ณผ๋ค์ ์ ํํ๋ ์ ๋๊ฐ ๋ค๋ฆ
: ๋ฉํฐ์ฐ๋ ๋์์ ๊ณต์ ๋ฉ๋ชจ๋ฆฌ → ๋ค๋ฅธ ์ฝ์ด์์ ๋ดค์ ๋ ์ ๋ฐ์ดํธ ์์๊ฐ ํ๋ฆด ์ ์์ผ๋ฉฐ ๋ฉ๋ชจ๋ฆฌ์ ๋ด์ฉ์ด ํ ์๊ฐ์ ์ ๋ฐ์ดํธ ๋์ง ์์ ๋๋ ์กด์ฌํจ
→ ์ด๋ป๊ฒ ํด์ผ ํ๋๊ฐ?
1) ์์ ์ํฉ์ ๊ฐ์ํ๊ณ ํ๋ก๊ทธ๋๋ฐ → ๋๋ฌด ์ด๋ ต๋ค. ํผํฐ์จ ์๊ณ ๋ฆฌ์ฆ๋ ๋์X
2) ๊ฐ์ ๋ก ์ํ๋ ๊ฒฐ๊ณผ๋ฅผ ์ป๋๋ก ํ๋ค → ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ์ mutex ์ฒ๋ฆฌ → ์ฑ๋ฅ ์ ํ
ํน์ atomic_thread_fence()๋ช ๋ น์ด → ์ฐพ์ ์์น๊ฐ ์๋ฒฝํ๋ค๋ ๋ณด์ฅ์?
→ ๊ผญ ํ์ํ ๊ณณ์ ์ฌ์ฉ atomic_thread_fence() ์ฌ์ฉ ํน์ ๊ณต์ ๋ณ์๋ก atomicํ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ
์ ๋ช ๋ น์ด๋ค์ ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ์ด ๋๋๊ธฐ ์ ๊น์ง ๋ค์ ์๋ ๋ช ๋ น์ด๋ค์ ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ์ ๋ง์
* ๋ฉ๋ชจ๋ฆฌ์ ๋ํ ์ฐ๊ธฐ๋ ์ธ์ ๊ฐ๋ ์๋ฃ ๋๋ค.
* ์๊ธฐ ์์ ์ ํ๋ก๊ทธ๋จ ์คํ ์์๋ ์ง์ผ์ง๋ค.
* ์บ์์ ์ผ๊ด์ฑ์ ์ง์ผ์ง๋ค.
- ํ๋ฒ ์ง์์ก๋ ๊ฐ์ด ๋ค์ ์ด์๋์ง๋ ์๋๋ค.
- ์ธ์ ๊ฐ๋ ๋ชจ๋ ์ฝ์ด๊ฐ ๋์ผํ ๊ฐ์ ๋ณธ๋ค.
* ์บ์๋ผ์ธ ๋ด๋ถ์ ์ฝ๊ธฐ/์ฐ๊ธฐ๋ ์ค๊ฐ ๊ฐ์ ๋ง๋ค์ง ์๋๋ค.
→ atomic memory๋ง ์์ผ๋ฉด ๋๋๊ฐ? No.
→ ์ค์ ์ฌ์ฉ ํ๋ก๊ทธ๋จ์ ๊ธฐ๋ณธ ์๋ฃํ๋ง์ ๊ฐ๊ณ ๊ฐ๋ฐ ํ ์ ์์. ๋ค์ํ ์๋ฃ๊ตฌ์กฐ๋ฅผ ์ด์ฉํด์ผ ํ๋ค.
→ atomicํ ์๋ฃ๊ตฌ์กฐ ํ์
: ์ ๊ทผ(๋ฉ๋ชจ๋ฆฌ๋ read, write)์ ์ ๋ ์์๊ฐ ๋ชจ๋ ์ฐ๋ ๋์์ ์ง์ผ์ง๋ ์๋ฃ๊ตฌ์กฐ
→ atomic Memory๋ฅผ ์ฌ์ฉํ์ฌ ๋ง๋ ์๋ฃ๊ตฌ์กฐ๊ฐ atomicํ๊ฐ ? No
→ ์ผ๋ฐ ์๋ฃ๊ตฌ์กฐ์ Lock (๋๋ฌด ๋๋ฆผ), STL (CRASH), STL+LOCK (๋๋ฌด ๋๋ฆผ)
→ Non-blocking ์๊ณ ๋ฆฌ์ฆ์ด ํจ์จ์ ์( O() )
- Non-Blocking
: ๋ค๋ฅธ ์ฐ๋ ๋์ ์๊ด์์ด ์งํ๋จ (ex. ๊ณต์ ๋ฉ๋ชจ๋ฆฌ ์ฝ๊ธฐ/์ฐ๊ธฐ ...)
: vs Blocking(๋ธ๋ญํน) - ๋ค๋ฅธ ์ฐ๋ ๋ ์งํ ์ํ์ ๋ฐ๋ผ ์งํ์ด ๋งํ ์ ์์ (ex. Lock ...)
: ๋ธ๋ญํน ์๊ณ ๋ฆฌ์ฆ์ ๋ค์๊ณผ ๊ฐ์ ๋ฌธ์ ๊ฐ ์๋ค.
1) ์ฑ๋ฅ ์ ํ
2) Priority Inversion : Lock์ ๊ณต์ ํ๋ ๋ ์ค์ํ ์์ ๋ค์ด ์ค์ํ ์์ ์ ์คํ์ ๋ง๋ ํ์ (Reader/Write Problem์์ ์์ฃผ ๋ฐ์ํจ)
3) Convoying : Lock์ ์ป์ ์ฐ๋ ๋๊ฐ ์ค์ผ์ฅด๋ง์์ ์ ์ธ๋ ๊ฒฝ์ฐ, lock์ ๊ธฐ๋ค๋ฆฌ๋ ๋ชจ๋ ์ฐ๋ ๋๊ฐ ๊ณตํ์ (์ฝ์ด๋ณด๋ค ๋ง์ ์์ ์ฐ๋ ๋๋ฅผ ์์ฑํ์ ๊ฒฝ์ฐ ์์ฃผ ๋ฐ์ํจ )
: Non-blocking ๋ฑ๊ธ : ์ฐ๋ ๋ ์ฌ์ด ํจ์จ์ ์๋ฃ ๊ตํ์ ์ํด์ ๊ผญ ํ์
1) ๋ฌด๋๊ธฐ (wait-free) : ๋ชจ๋ ๋ฉ์๋๊ฐ ์ ํด์ง ์ ํ ๋จ๊ณ์ ์คํ์ ๋ง์น๋ฉฐ ๋ฉ์ถค ์๋ ํ๋ก๊ทธ๋จ์ ์คํํจ
2) ๋ฌด์ ๊ธ (lock-free) : ํญ์, ์ ์ด๋ ํ ๊ฐ์ ๋ฉ์๋๊ฐ ์ ํํ ๋จ๊ณ์ ์คํ์ ๋๋ง์นจ. ๋ฌด๋๊ธฐ๋ฉด ๋ฌด์ ๊ธ์ด๋ฉฐ ๊ธฐ์๋ฅผ ์ ๋ฐํ๊ธฐ ๋ํจ. ์ฑ๋ฅ์ ์ํด ๋ฌด๋๊ธฐ ๋์ ๋ฌด์ ๊ธ ์ ํํ๊ธฐ๋ ํจ.
3) ์ ํ๋ ๋ฌด๋๊ธฐ : ์ ํํ์ง๋ง ์ฐ๋ ๋ ๊ฐ์์ ๋น๋กํ ์ ํ์ผ ์ ์์
4) ๋ฌด๊ฐ์ญ(obstruction-free) : ํ ๊ฐ๋ฅผ ์ ์ธํ ๋ชจ๋ ์ฐ๋ ๋๊ฐ ๋ฉ์ถ์์ ๋, ๋ฉ์ถ์ง ์์ ์ฐ๋ ๋์ ๋ฉ์๋๊ฐ ์ ํํ ๋จ๊ณ์ ์ข ๋ฃํ ๋. ์ถฉ๋ ์ค์ธ ์ฐ๋ ๋๋ฅผ ์ ๊น ๋ฉ์ถ ํ์๊ฐ ์กด์ฌ
'๐ค Study > MultiThread' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[06~08์ฃผ์ฐจ] Non-Blocking ์๊ณ ๋ฆฌ์ฆ - LIST (0) | 2024.04.25 |
---|---|
[05์ฃผ์ฐจ] ๋๊ธฐํ ์ฐ์ฐ & CAS (0) | 2024.04.24 |
[03์ฃผ์ฐจ] ๋ฉํฐ์ฐ๋ ๋ ํ๋ก๊ทธ๋๋ฐ ์ฃผ์์ฌํญ & ์ํธ๋ฐฐ์ ์๊ณ ๋ฆฌ์ฆ (1) | 2024.04.18 |
[02์ฃผ์ฐจ] ๋ฉํฐ์ฝ์ด HW & DataRace (0) | 2024.04.18 |
[01์ฃผ์ฐจB] ๋ฉํฐ์ฝ์ด HW & ๋ฉํฐ์ฐ๋ ๋ํ๋ก๊ทธ๋๋ฐ ์์ (0) | 2024.03.28 |