League Of Legends - Link Select [04์ฃผ์ฐจ] ๋ฉ”๋ชจ๋ฆฌ ์ผ๊ด€์„ฑ
๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿค“ Study/MultiThread

[04์ฃผ์ฐจ] ๋ฉ”๋ชจ๋ฆฌ ์ผ๊ด€์„ฑ

by GAMEMING 2024. 4. 18.
728x90

 

- 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๋ผ๋ฆฌ๋งŒ ์ˆœ์„œ๋ฅผ ๋งž์ถฐ์ฃผ๊ธฐ์— ์ž์‹  ์—†์Œ ๋‘˜๋‹ค atomic์œผ๋กœ ํ•ด๋ผ

 

 : ๋ฉ”๋ชจ๋ฆฌ ์ ‘๊ทผ์ด 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) : ํ•œ ๊ฐœ๋ฅผ ์ œ์™ธํ•œ ๋ชจ๋“  ์“ฐ๋ ˆ๋“œ๊ฐ€ ๋ฉˆ์ถ”์—ˆ์„ ๋•Œ, ๋ฉˆ์ถ”์ง€ ์•Š์€ ์“ฐ๋ ˆ๋“œ์˜ ๋ฉ”์†Œ๋“œ๊ฐ€ ์œ ํ•œํ•œ ๋‹จ๊ณ„์— ์ข…๋ฃŒํ•  ๋•Œ. ์ถฉ๋Œ ์ค‘์ธ ์“ฐ๋ ˆ๋“œ๋ฅผ ์ž ๊น ๋ฉˆ์ถœ ํ•„์š”๊ฐ€ ์กด์žฌ