๐ ์บ์ ์นํ์ ์ธ C ์ฝ๋ ์์ฑ๋ฒ: ์ฑ๋ฅ์ ๋น๋ฐ์ ํ๋ค ๐

์๋ ํ์ธ์, ์ฝ๋ฉ ๋ง๋ฒ์ฌ ์ฌ๋ฌ๋ถ! ์ค๋์ ์์ฃผ ํน๋ณํ ์ฌํ์ ๋ ๋๋ณผ ๊ฑฐ์์. ๋ฐ๋ก C ์ธ์ด์ ์จ๊ฒจ์ง ๋ณด๋ฌผ, '์บ์ ์นํ์ ์ธ ์ฝ๋ ์์ฑ๋ฒ'์ ๋ํด ์์๋ณผ ๊ฑฐ๋๋๋ค. ๐งโโ๏ธโจ
์ฌ๋ฌ๋ถ, ํน์ ํ๋ก๊ทธ๋จ์ด ๊ฑฐ๋ถ์ด์ฒ๋ผ ๋๋ฆฌ๊ฒ ์์ง์ด๋ ๊ฒฝํ์ ํด๋ณด์ จ๋์? ์๋๋ฉด ์ปดํจํฐ๊ฐ ์ด์ ๋ด๋ฟ์ผ๋ฉฐ ํ๊ฒน๊ฒ ๋์๊ฐ๋ ๊ฑธ ๋ณธ ์ ์์ผ์ ๊ฐ์? ๊ทธ๋ ๋ค๋ฉด ์ค๋์ ์ฃผ์ ๋ ์ฌ๋ฌ๋ถ์๊ฒ ๊ผญ ํ์ํ ๋ง๋ฒ ์ฃผ๋ฌธ์ด ๋ ๊ฑฐ์์!
๐ก ์๊ณ ๊ณ์ จ๋์? ์บ์ ์นํ์ ์ธ ์ฝ๋๋ฅผ ์์ฑํ๋ฉด, ์ฌ๋ฌ๋ถ์ ํ๋ก๊ทธ๋จ์ด ๋ง์น ๋ก์ผ์ฒ๋ผ ๋น ๋ฅด๊ฒ ์คํ๋ ์ ์๋ต๋๋ค!
์, ๊ทธ๋ผ ์ด์ ๋ถํฐ C ์ธ์ด์ ์ฑ๋ฅ ๋น๋ฐ์ ํ๋์ฉ ํ์ด๋๊ฐ ๋ณผ๊น์? ์ฐ๋ฆฌ์ ์ฌ์ ์ด ๋๋ ์ฆ์์, ์ฌ๋ฌ๋ถ๋ ์บ์์ ๋ฌ์ธ์ด ๋์ด ์์ ๊ฑฐ์์! ๐
๊ทธ๋ฆฌ๊ณ ์ ๊น! ์ด๋ฐ ๋ฉ์ง ํ๋ก๊ทธ๋๋ฐ ๊ธฐ์ ์ ๋ฐฐ์ฐ๊ณ ๋๋ฉด, ์ฌ๋ฌ๋ถ์ ์ฌ๋ฅ์ ๋ค๋ฅธ ์ฌ๋๋ค๊ณผ ๋๋๊ณ ์ถ์ด์ง ์๋ ์์ด์. ๊ทธ๋ด ๋๋ ์ฌ๋ฅ๋ท์ด๋ผ๋ ํ๋ซํผ์ ๊ธฐ์ตํด๋์ธ์. ์ฌ๊ธฐ์ ์ฌ๋ฌ๋ถ์ ์๋ก์ด ๊ธฐ์ ์ ๊ณต์ ํ๊ณ , ๋ ๋ค๋ฅธ ํฅ๋ฏธ๋ก์ด ์ฌ๋ฅ๋ค๋ ๋ง๋๋ณผ ์ ์๋ต๋๋ค! ๐
์, ์ด์ ์ ๋ง๋ก ์์ํด๋ณผ๊น์? ์บ์์ ์ธ๊ณ๋ก ๋ฐ์ด๋ค ์ค๋น ๋์ จ๋์? Let's go! ๐
๐ง ์บ์(Cache)๋ ๋ฌด์์ผ๊น์?
์ฐ๋ฆฌ์ ์ฌ์ ์ ์์ํ๊ธฐ ์ ์, ๋จผ์ '์บ์'๋ผ๋ ๊ฒ์ด ๋ฌด์์ธ์ง ์์๋ณผ ํ์๊ฐ ์์ด์. ์บ์๋ ๋ง์น ์ฐ๋ฆฌ ๋์ ๋จ๊ธฐ ๊ธฐ์ต์ฅ์น์ ๋น์ทํ ์ญํ ์ ํ๋ต๋๋ค. ๐ง ๐ญ
์บ์(Cache)์ ์ ์: ์ปดํจํฐ ์์คํ ์์ ์์ฃผ ์ฌ์ฉ๋๋ ๋ฐ์ดํฐ๋ ๊ฐ์ ์์๋ก ์ ์ฅํด๋๋ ๊ณ ์์ ๊ธฐ์ต ์ฅ์น๋ฅผ ๋งํฉ๋๋ค.
์บ์๋ CPU์ ์ฃผ ๋ฉ๋ชจ๋ฆฌ(RAM) ์ฌ์ด์ ์์นํ๋ฉฐ, ๋ฐ์ดํฐ๋ฅผ ๋น ๋ฅด๊ฒ ์ฃผ๊ณ ๋ฐ์ ์ ์๊ฒ ํด์ค๋๋ค. ๋ง์น ํ๊ต์์ ์ฌ๋ฌผํจ์ ์ฌ์ฉํ๋ ๊ฒ๊ณผ ๋น์ทํ์ฃ . ์์ฃผ ์ฐ๋ ์ฑ ์ ์ฌ๋ฌผํจ์ ๋ฃ์ด๋๊ณ , ํ์ํ ๋๋ง๋ค ๋น ๋ฅด๊ฒ ๊บผ๋ด ์ฐ๋ ๊ฒ์ฒ๋ผ์! ๐๐
์บ์์ ์ข ๋ฅ
์บ์์๋ ์ฌ๋ฌ ์ข ๋ฅ๊ฐ ์๋ต๋๋ค. ์ฃผ๋ก ๋ค์๊ณผ ๊ฐ์ด ๋๋ ์ ์์ด์:
- L1 ์บ์: CPU์ ๊ฐ์ฅ ๊ฐ๊น์ด ์๋ ์บ์๋ก, ์๋๊ฐ ๊ฐ์ฅ ๋น ๋ฅด์ง๋ง ์ฉ๋์ด ์์์.
- L2 ์บ์: L1๋ณด๋ค๋ ์กฐ๊ธ ๋๋ฆฌ์ง๋ง, ๋ ํฐ ์ฉ๋์ ๊ฐ์ง๊ณ ์์ด์.
- L3 ์บ์: ์ผ๋ถ ๊ณ ์ฑ๋ฅ ํ๋ก์ธ์์์ ์ฌ์ฉ๋๋ฉฐ, L2๋ณด๋ค ๋ ํฐ ์ฉ๋์ ์ ๊ณตํด์.
์ด๋ฐ ์บ์๋ค์ด ํจ์จ์ ์ผ๋ก ์๋ํ ๋, ์ฐ๋ฆฌ์ ํ๋ก๊ทธ๋จ์ ๋ง์น ๋ฒ๊ฐ์ฒ๋ผ ๋น ๋ฅด๊ฒ ๋์ํ ์ ์๋ต๋๋ค! โก๏ธ
์บ์๊ฐ ์ค์ํ ์ด์
์ฌ๋ฌ๋ถ, ํน์ ์ปดํจํฐ๊ฐ ๊ณ์ฐ์ ํ ๋ ์ด๋ค ์ผ์ด ์ผ์ด๋๋์ง ๊ถ๊ธํ์ จ๋์? ๊ฐ๋จํ ์ค๋ช ํด๋๋ฆด๊ฒ์:
- CPU๊ฐ ๋ฐ์ดํฐ๋ ๋ช ๋ น์ด๋ฅผ ์์ฒญํฉ๋๋ค. ๐ฅ๏ธ
- ๋จผ์ ์บ์๋ฅผ ํ์ธํฉ๋๋ค. ์ฌ๊ธฐ ์์ผ๋ฉด ๋ฐ๋ก ์ฌ์ฉ! ๐
- ์บ์์ ์๋ค๋ฉด, ๋ฉ์ธ ๋ฉ๋ชจ๋ฆฌ(RAM)์์ ๊ฐ์ ธ์ต๋๋ค. ๐ถโโ๏ธ
- RAM์๋ ์๋ค๋ฉด, ํ๋ ๋์คํฌ์์ ๊ฐ์ ธ์์ผ ํด์. ์ด๊ฑด ์ ๋ง ๋๋ ค์! ๐ข
๋ณด์ จ๋์? ์บ์์์ ๋ฐ์ดํฐ๋ฅผ ์ฐพ์ผ๋ฉด ์์ฒญ๋๊ฒ ๋น ๋ฅด๊ฒ ์์ ์ ์ฒ๋ฆฌํ ์ ์์ด์. ๊ทธ๋์ ์ฐ๋ฆฌ๋ ์บ์ ์นํ์ ์ธ ์ฝ๋๋ฅผ ์์ฑํ๋ ๊ฒ์ด ์ค์ํ ๊ฑฐ๋๋๋ค!
๐ ์ฌ๋ฅ๋ท ํ: ์บ์ ์ต์ ํ ๊ธฐ์ ์ ํ๋ก๊ทธ๋๋ฐ ๋ถ์ผ์์ ๋งค์ฐ ๊ฐ์น ์๋ ๊ธฐ์ ์ด์์. ์ด๋ฐ ๊ธฐ์ ์ ์ตํ๋ฉด, ์ฌ๋ฅ๋ท์์ ์ฌ๋ฌ๋ถ์ ์ฌ๋ฅ์ ๊ณต์ ํ๊ณ ๋ค๋ฅธ ๊ฐ๋ฐ์๋ค์๊ฒ ๋์์ ์ค ์ ์์ ๊ฑฐ์์!
์, ์ด์ ์บ์๊ฐ ๋ฌด์์ธ์ง, ์ ์ค์ํ์ง ์๊ฒ ๋์ จ์ฃ ? ๋ค์ ์น์ ์์๋ ์ค์ ๋ก C ์ธ์ด์์ ์ด๋ป๊ฒ ์บ์ ์นํ์ ์ธ ์ฝ๋๋ฅผ ์์ฑํ ์ ์๋์ง ์์ธํ ์์๋ณด๋๋ก ํด์. ์ค๋น๋์ จ๋์? Let's dive deeper! ๐โโ๏ธ๐ป
๐ C ์ธ์ด์์์ ์บ์ ์นํ์ ์ฝ๋ฉ: ๊ธฐ๋ณธ ์์น
์, ์ด์ ๋ณธ๊ฒฉ์ ์ผ๋ก C ์ธ์ด์์ ์ด๋ป๊ฒ ์บ์ ์นํ์ ์ธ ์ฝ๋๋ฅผ ์์ฑํ ์ ์๋์ง ์์๋ณผ ์๊ฐ์ด์์! ๐ต๏ธโโ๏ธ ์ฌ๋ฌ๋ถ, ๋ง๋ฒ์ฌ์ ์งํก์ด๋ฅผ ๊บผ๋ด๋ค ์ค๋น๊ฐ ๋์ จ๋์? ๊ทธ๋ผ ์์ํด๋ณผ๊น์?
1. ๋ฐ์ดํฐ ์ง์ญ์ฑ(Data Locality) ํ์ฉํ๊ธฐ
๋ฐ์ดํฐ ์ง์ญ์ฑ์ด๋, ํ๋ก๊ทธ๋จ์ด ๊ฐ๊น์ด ๋ฉ๋ชจ๋ฆฌ ์์น์ ๋ฐ์ดํฐ๋ฅผ ์์ฃผ ์ ๊ทผํ๋ ๊ฒฝํฅ์ ๋งํด์. ์ด๋ฅผ ์ ํ์ฉํ๋ฉด ์บ์ ํํธ์จ์ ๋์ผ ์ ์๋ต๋๋ค!
์๊ฐ์ ์ง์ญ์ฑ (Temporal Locality)
์ต๊ทผ์ ์ ๊ทผํ ๋ฐ์ดํฐ๋ ๊ณง ๋ค์ ์ ๊ทผ๋ ๊ฐ๋ฅ์ฑ์ด ๋์์. ์ด๊ฑธ ์๊ฐ์ ์ง์ญ์ฑ์ด๋ผ๊ณ ํด์.
์์: ๋ฃจํ์์ ๊ฐ์ ๋ณ์๋ฅผ ๋ฐ๋ณตํด์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ
for (int i = 0; i < 1000; i++) {
sum += data[i]; // 'sum'์ ๋งค ๋ฐ๋ณต๋ง๋ค ์ฌ์ฉ๋ฉ๋๋ค.
}
์ ์ฝ๋์์ 'sum' ๋ณ์๋ ๋งค ๋ฐ๋ณต๋ง๋ค ์ฌ์ฉ๋๋ฏ๋ก, ์บ์์ ๊ณ์ ๋จ์์์ ๊ฐ๋ฅ์ฑ์ด ๋์์. ์ด๋ ๊ฒ ํ๋ฉด ๋ฉ๋ชจ๋ฆฌ์์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๋ ์๊ฐ์ ํฌ๊ฒ ์ค์ผ ์ ์๋ต๋๋ค! ๐
๊ณต๊ฐ์ ์ง์ญ์ฑ (Spatial Locality)
๋ฉ๋ชจ๋ฆฌ์์์ ๊ฐ๊น์ด ์์นํ ๋ฐ์ดํฐ๋ค์ ํจ๊ป ์ฌ์ฉ๋ ๊ฐ๋ฅ์ฑ์ด ๋์์. ์ด๊ฑธ ๊ณต๊ฐ์ ์ง์ญ์ฑ์ด๋ผ๊ณ ํด์.
์์: ๋ฐฐ์ด์ ์์ฐจ์ ์ผ๋ก ์ ๊ทผํ๋ ๊ฒฝ์ฐ
int arr[1000];
for (int i = 0; i < 1000; i++) {
arr[i] = i; // ๋ฐฐ์ด์ ์์ฐจ์ ์ผ๋ก ์ ๊ทผํฉ๋๋ค.
}
์ด ์ฝ๋์์๋ ๋ฐฐ์ด 'arr'์ ์์ฐจ์ ์ผ๋ก ์ ๊ทผํ๊ณ ์์ด์. ์บ์๋ ๋ณดํต ํ ๋ฒ์ ์ฌ๋ฌ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๊ธฐ ๋๋ฌธ์, ์ด๋ฐ ๋ฐฉ์์ผ๋ก ์ ๊ทผํ๋ฉด ์บ์ ํจ์จ์ด ๋์์ง๋ต๋๋ค! ๐
2. ์บ์ ๋ผ์ธ ํฌ๊ธฐ ๊ณ ๋ คํ๊ธฐ
์บ์๋ '์บ์ ๋ผ์ธ'์ด๋ผ๋ ๋จ์๋ก ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์์. ๋ณดํต 64๋ฐ์ดํธ ์ ๋ ๋๋๋ฐ, ์ด ํฌ๊ธฐ๋ฅผ ๊ณ ๋ คํด์ ์ฝ๋๋ฅผ ์์ฑํ๋ฉด ๋ ํจ์จ์ ์ผ ์ ์์ด์.
ํ: ๊ตฌ์กฐ์ฒด(struct)๋ฅผ ์ค๊ณํ ๋, ์์ฃผ ํจ๊ป ์ฌ์ฉ๋๋ ๋ฉค๋ฒ๋ค์ ๊ฐ๊น์ด ๋ฐฐ์นํ๊ณ , ์ ์ฒด ํฌ๊ธฐ๋ฅผ ์บ์ ๋ผ์ธ์ ๋ฐฐ์์ ๊ฐ๊น๊ฒ ๋ง๋ค์ด๋ณด์ธ์!
// ์ข์ ์:
struct GoodStruct {
int frequently_used1;
int frequently_used2;
char rarely_used[60]; // ํจ๋ฉ์ผ๋ก ์ฌ์ฉ
}; // ์ด 68๋ฐ์ดํธ (64๋ฐ์ดํธ ์บ์ ๋ผ์ธ์ ๊ฐ๊น์)
// ๋์ ์:
struct BadStruct {
int frequently_used1;
char rarely_used[60];
int frequently_used2;
}; // ์บ์ ๋ผ์ธ์ ํจ์จ์ ์ผ๋ก ์ฌ์ฉํ์ง ๋ชปํจ
'GoodStruct'๋ ์์ฃผ ์ฌ์ฉ๋๋ ๋ฉค๋ฒ๋ค์ ํจ๊ป ๋ฐฐ์นํด์ ์บ์ ํจ์จ์ ๋์์ด์. ๋ฐ๋ฉด 'BadStruct'๋ ์์ฃผ ์ฌ์ฉ๋๋ ๋ฉค๋ฒ๋ค ์ฌ์ด์ ํฐ ๋ฐ์ดํฐ๊ฐ ์์ด์ ์บ์ ํจ์จ์ด ๋จ์ด์ง ์ ์๋ต๋๋ค.
3. ๋ฃจํ ์ต์ ํํ๊ธฐ
๋ฃจํ๋ ํ๋ก๊ทธ๋จ์์ ๊ฐ์ฅ ์๊ฐ์ ๋ง์ด ์๋นํ๋ ๋ถ๋ถ ์ค ํ๋์์. ๊ทธ๋์ ๋ฃจํ๋ฅผ ์ต์ ํํ๋ฉด ์ ์ฒด ์ฑ๋ฅ์ ํฌ๊ฒ ํฅ์์ํฌ ์ ์๋ต๋๋ค!
๋ฃจํ ์ธ๋กค๋ง (Loop Unrolling)
๋ฃจํ ์ธ๋กค๋ง์ ๋ฃจํ ๋ด๋ถ์ ์ฝ๋๋ฅผ ํผ์ณ์ ๋ฐ๋ณต ํ์๋ฅผ ์ค์ด๋ ๊ธฐ๋ฒ์ด์์. ์ด๋ ๊ฒ ํ๋ฉด ๋ฃจํ ์ค๋ฒํค๋๋ฅผ ์ค์ด๊ณ ๋ณ๋ ฌ ์ฒ๋ฆฌ ๊ธฐํ๋ฅผ ๋๋ฆด ์ ์์ด์.
์์: ๋ฃจํ ์ธ๋กค๋ง ์ ์ฉํ๊ธฐ
// ๊ธฐ๋ณธ ๋ฃจํ
for (int i = 0; i < 1000; i++) {
sum += data[i];
}
// ์ธ๋กค๋ง ์ ์ฉ
for (int i = 0; i < 1000; i += 4) {
sum += data[i];
sum += data[i+1];
sum += data[i+2];
sum += data[i+3];
}
์ธ๋กค๋ง์ ์ ์ฉํ ๋ฒ์ ์์๋ ๋ฃจํ ๋ฐ๋ณต ํ์๊ฐ 1/4๋ก ์ค์ด๋ค์์ด์. ์ด๋ ๊ฒ ํ๋ฉด ๋ฃจํ ์นด์ดํฐ๋ฅผ ์ ๋ฐ์ดํธํ๊ณ ์กฐ๊ฑด์ ์ฒดํฌํ๋ ํ์๊ฐ ์ค์ด๋ค์ด ์ฑ๋ฅ์ด ํฅ์๋ ์ ์๋ต๋๋ค! ๐๏ธ๐จ
์บ์ ๋ธ๋กํน (Cache Blocking)
๋์ฉ๋ ๋ฐ์ดํฐ๋ฅผ ๋ค๋ฃฐ ๋, ์บ์ ๋ธ๋กํน ๊ธฐ๋ฒ์ ์ฌ์ฉํ๋ฉด ์บ์ ํจ์จ์ ํฌ๊ฒ ๋์ผ ์ ์์ด์. ์ด ๊ธฐ๋ฒ์ ๋ฐ์ดํฐ๋ฅผ ์บ์ ํฌ๊ธฐ์ ๋ง๋ ์์ ๋ธ๋ก์ผ๋ก ๋๋์ด ์ฒ๋ฆฌํ๋ ๋ฐฉ์์ด์์.
์์: ํ๋ ฌ ๊ณฑ์ ์ ์บ์ ๋ธ๋กํน ์ ์ฉํ๊ธฐ
#define BLOCK_SIZE 32
void matrix_multiply(int n, double *A, double *B, double *C) {
for (int i = 0; i < n; i += BLOCK_SIZE) {
for (int j = 0; j < n; j += BLOCK_SIZE) {
for (int k = 0; k < n; k += BLOCK_SIZE) {
// ๋ธ๋ก ๋จ์๋ก ํ๋ ฌ ๊ณฑ์
for (int ii = i; ii < i + BLOCK_SIZE && ii < n; ++ii) {
for (int jj = j; jj < j + BLOCK_SIZE && jj < n; ++jj) {
for (int kk = k; kk < k + BLOCK_SIZE && kk < n; ++kk) {
C[ii * n + jj] += A[ii * n + kk] * B[kk * n + jj];
}
}
}
}
}
}
}
์ด ์์ ์์๋ ํฐ ํ๋ ฌ์ 32x32 ํฌ๊ธฐ์ ์์ ๋ธ๋ก์ผ๋ก ๋๋์ด ์ฒ๋ฆฌํ๊ณ ์์ด์. ์ด๋ ๊ฒ ํ๋ฉด ๊ฐ ๋ธ๋ก์ด ์บ์์ ์์ ํ ๋ค์ด๊ฐ ์ ์์ด, ์บ์ ๋ฏธ์ค๋ฅผ ํฌ๊ฒ ์ค์ผ ์ ์๋ต๋๋ค! ๐งฉโจ
4. ๋ถ๊ธฐ ์์ธก ์ต์ ํ
ํ๋์ CPU๋ ๋ถ๊ธฐ ์์ธก(Branch Prediction)์ด๋ผ๋ ๊ธฐ๋ฅ์ ์ฌ์ฉํด ์ฑ๋ฅ์ ๋์ด๊ณ ์์ด์. ํ์ง๋ง ์์ธก์ด ํ๋ฆฌ๋ฉด ์คํ๋ ค ์ฑ๋ฅ์ด ๋จ์ด์ง ์ ์์ฃ . ๊ทธ๋์ ๊ฐ๋ฅํ๋ฉด ๋ถ๊ธฐ๋ฅผ ์ค์ด๋ ๊ฒ์ด ์ข์์.
ํ: ์กฐ๊ฑด๋ฌธ ๋์ ๋นํธ ์ฐ์ฐ์ด๋ ๋ฃฉ์ ํ ์ด๋ธ์ ์ฌ์ฉํ๋ฉด ๋ถ๊ธฐ๋ฅผ ์ค์ผ ์ ์์ด์!
// ๋ถ๊ธฐ๊ฐ ๋ง์ ๋ฒ์
int get_sign(int x) {
if (x > 0) return 1;
else if (x < 0) return -1;
else return 0;
}
// ๋ถ๊ธฐ๋ฅผ ์ ๊ฑฐํ ๋ฒ์
int get_sign(int x) {
return (x > 0) - (x < 0);
}
๋ ๋ฒ์งธ ๋ฒ์ ์์๋ ์กฐ๊ฑด๋ฌธ ๋์ ์ฐ์ ์ฐ์ฐ์ ์ฌ์ฉํด ๋ถ๊ธฐ๋ฅผ ์ ๊ฑฐํ์ด์. ์ด๋ ๊ฒ ํ๋ฉด CPU๊ฐ ๋ ํจ์จ์ ์ผ๋ก ์๋ํ ์ ์๋ต๋๋ค! ๐ง โก
5. ๋ฉ๋ชจ๋ฆฌ ์ ๋ ฌ (Memory Alignment)
๋ฐ์ดํฐ๋ฅผ ๋ฉ๋ชจ๋ฆฌ์ ์ ์ฅํ ๋, ์ ์ ํ ์ ๋ ฌํ๋ฉด ์บ์ ํจ์จ์ ๋์ผ ์ ์์ด์. C์ธ์ด์์๋ ๊ตฌ์กฐ์ฒด ๋ฉค๋ฒ์ ์ ๋ ฌ์ ํนํ ์ฃผ์ํด์ผ ํด์.
์์: ๊ตฌ์กฐ์ฒด ๋ฉค๋ฒ ์ ๋ ฌ ์ต์ ํ
// ๋นํจ์จ์ ์ธ ๊ตฌ์กฐ์ฒด
struct BadStruct {
char a; // 1๋ฐ์ดํธ
double b; // 8๋ฐ์ดํธ
int c; // 4๋ฐ์ดํธ
char d; // 1๋ฐ์ดํธ
}; // ์ด 24๋ฐ์ดํธ (ํจ๋ฉ ๋๋ฌธ)
// ์ต์ ํ๋ ๊ตฌ์กฐ์ฒด
struct GoodStruct {
double b; // 8๋ฐ์ดํธ
int c; // 4๋ฐ์ดํธ
char a; // 1๋ฐ์ดํธ
char d; // 1๋ฐ์ดํธ
// 2๋ฐ์ดํธ ํจ๋ฉ
}; // ์ด 16๋ฐ์ดํธ
'GoodStruct'๋ ๋ฉค๋ฒ๋ค์ ํฌ๊ธฐ ์์ผ๋ก ๋ฐฐ์ดํด ํจ๋ฉ์ ์ต์ํํ์ด์. ์ด๋ ๊ฒ ํ๋ฉด ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋๋ ์ค์ด๊ณ , ์บ์ ํจ์จ๋ ๋์ผ ์ ์๋ต๋๋ค! ๐ฆโจ
๐ ์ฌ๋ฅ๋ท ํ: ์ด๋ฐ ์ต์ ํ ๊ธฐ๋ฒ๋ค์ ์ค์ ํ๋ก์ ํธ์์ ๋งค์ฐ ์ ์ฉํด์. ์ฌ๋ฌ๋ถ์ด ์ด๋ฐ ๊ธฐ์ ์ ์ตํ๊ณ ์ฌ๋ฅ๋ท์์ ๊ณต์ ํ๋ค๋ฉด, ๋ง์ ๊ฐ๋ฐ์๋ค์๊ฒ ๋์์ด ๋ ๊ฑฐ์์!
์, ์ฌ๊ธฐ๊น์ง C ์ธ์ด์์ ์บ์ ์นํ์ ์ธ ์ฝ๋๋ฅผ ์์ฑํ๋ ๊ธฐ๋ณธ ์์น๋ค์ ์์๋ดค์ด์. ์ด ์์น๋ค์ ์ ์ ์ฉํ๋ฉด, ์ฌ๋ฌ๋ถ์ ํ๋ก๊ทธ๋จ์ ๋ง์น ์์ ์ด ๋ง๋ฒ์ ๋ถ๋ฆฐ ๊ฒ์ฒ๋ผ ๋น ๋ฅด๊ฒ ๋์ํ ๊ฑฐ์์! ๐งโโ๏ธโจ
๋ค์ ์น์ ์์๋ ์ด๋ฐ ์์น๋ค์ ์ค์ ์ฝ๋์ ์ด๋ป๊ฒ ์ ์ฉํ๋์ง, ๋ ์์ธํ ์์ ์ ํจ๊ป ์ดํด๋ณผ ๊ฑฐ์์. ์ค๋น๋์ จ๋์? Let's code like a pro! ๐ป๐
๐ ๏ธ ์ค์ ์์ : ์บ์ ์นํ์ C ์ฝ๋ ์์ฑํ๊ธฐ
์, ์ด์ ์ฐ๋ฆฌ๊ฐ ๋ฐฐ์ด ์์น๋ค์ ์ค์ ์ฝ๋์ ์ ์ฉํด๋ณผ ์๊ฐ์ด์์! ๐จ ์ฌ๋ฌ๋ถ, ์ฝ๋ฉ ๋ถ์ ๋ค๊ณ ์บ๋ฒ์ค ์์ ์ ์ฃผ์ธ์. ์ฐ๋ฆฌ๋ ์ง๊ธ๋ถํฐ ์บ์ ์นํ์ ์ธ ์ฝ๋๋ผ๋ ๋ฉ์ง ๊ทธ๋ฆผ์ ๊ทธ๋ ค๋ณผ ๊ฑฐ์์!
1. ๋ฐฐ์ด ์ํ ์ต์ ํ
๋ฐฐ์ด์ ๋ค๋ฃฐ ๋, ์ด๋ป๊ฒ ์ํํ๋๋์ ๋ฐ๋ผ ์ฑ๋ฅ์ด ํฌ๊ฒ ๋ฌ๋ผ์ง ์ ์์ด์. ํนํ 2์ฐจ์ ๋ฐฐ์ด์ ๋ค๋ฃฐ ๋ ์ด ์ ์ด ์ค์ํด์.
์์ : 2์ฐจ์ ๋ฐฐ์ด ์ํ ์ต์ ํ
#define N 1000
#define M 1000
// ์บ์ ๋นํจ์จ์ ์ธ ๋ฒ์
void bad_traverse(int arr[N][M]) {
for (int j = 0; j < M; j++) {
for (int i = 0; i < N; i++) {
arr[i][j]++; // ์ด ์ฐ์ ์ํ
}
}
}
// ์บ์ ์นํ์ ์ธ ๋ฒ์
void good_traverse(int arr[N][M]) {
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
arr[i][j]++; // ํ ์ฐ์ ์ํ
}
}
}
'good_traverse' ํจ์๋ ํ ์ฐ์ ์ผ๋ก ๋ฐฐ์ด์ ์ํํด์. C์ธ์ด์์ 2์ฐจ์ ๋ฐฐ์ด์ ๋ฉ๋ชจ๋ฆฌ์ ํ ์ฐ์ ์ผ๋ก ์ ์ฅ๋๊ธฐ ๋๋ฌธ์, ์ด ๋ฐฉ์์ด ์บ์ ์นํ์ ์ด๋๋๋ค. ๋ง์น ์ฑ ์ ์ฝ์ ๋ ์ผ์ชฝ์์ ์ค๋ฅธ์ชฝ์ผ๋ก, ์์์ ์๋๋ก ์ฝ๋ ๊ฒ๊ณผ ๊ฐ์์! ๐๐
2. ๊ตฌ์กฐ์ฒด ํจ๋ฉ ์ต์ ํ
๊ตฌ์กฐ์ฒด๋ฅผ ์ค๊ณํ ๋ ๋ฉค๋ฒ ๋ณ์์ ์์๋ฅผ ์ ์ ํ ๋ฐฐ์นํ๋ฉด, ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ ์ค์ด๊ณ ์บ์ ํจ์จ์ ๋์ผ ์ ์์ด์.
์์ : ๊ตฌ์กฐ์ฒด ํจ๋ฉ ์ต์ ํ
// ๋นํจ์จ์ ์ธ ๊ตฌ์กฐ์ฒด
struct BadPerson {
char name[50]; // 50๋ฐ์ดํธ
int age; // 4๋ฐ์ดํธ
char gender; // 1๋ฐ์ดํธ
double salary; // 8๋ฐ์ดํธ
}; // ์ด 72๋ฐ์ดํธ (ํจ๋ฉ ํฌํจ)
// ์ต์ ํ๋ ๊ตฌ์กฐ์ฒด
struct GoodPerson {
char name[50]; // 50๋ฐ์ดํธ
double salary; // 8๋ฐ์ดํธ
int age; // 4๋ฐ์ดํธ
char gender; // 1๋ฐ์ดํธ
char padding[3];// 3๋ฐ์ดํธ (๋ช
์์ ํจ๋ฉ)
}; // ์ด 66๋ฐ์ดํธ
'GoodPerson' ๊ตฌ์กฐ์ฒด๋ ๋ฉค๋ฒ ๋ณ์๋ฅผ ํฌ๊ธฐ ์์ผ๋ก ๋ฐฐ์ดํ๊ณ , ๋ง์ง๋ง์ ๋ช ์์ ํจ๋ฉ์ ์ถ๊ฐํ์ด์. ์ด๋ ๊ฒ ํ๋ฉด ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋๋ ์ค์ด๊ณ ์บ์ ๋ผ์ธ๋ ํจ์จ์ ์ผ๋ก ์ฌ์ฉํ ์ ์๋ต๋๋ค! ๐งฉโจ
3. ๋ฃจํ ์ตํฉ (Loop Fusion)
์ฌ๋ฌ ๊ฐ์ ๋ฃจํ๋ฅผ ํ๋๋ก ํฉ์น๋ฉด ์บ์ ์ง์ญ์ฑ์ ๋์ด๊ณ ๋ฃจํ ์ค๋ฒํค๋๋ฅผ ์ค์ผ ์ ์์ด์.
์์ : ๋ฃจํ ์ตํฉ ์ ์ฉ
#define N 10000
// ์ตํฉ ์
void before_fusion(int* arr) {
for (int i = 0; i < N; i++) {
arr[i] *= 2;
}
for (int i = 0; i < N; i++) {
arr[i] += 5;
}
}
// ์ตํฉ ํ
void after_fusion(int* arr) {
for (int i = 0; i < N; i++) {
arr[i] = arr[i] * 2 + 5;
}
}
'after_fusion' ํจ์๋ ๋ ๊ฐ์ ๋ฃจํ๋ฅผ ํ๋๋ก ํฉ์ณค์ด์. ์ด๋ ๊ฒ ํ๋ฉด ๋ฐฐ์ด 'arr'์ ํ ๋ฒ๋ง ์ํํ๋ฉด ๋๋๊น, ์บ์ ํํธ์จ์ด ๋์์ง๊ณ ์คํ ์๊ฐ๋ ์ค์ด๋ค์ด์. ์ผ์์ด์กฐ๋ค์! ๐ฏ๐
4. ์กฐ๊ฑด๋ฌธ ์ต์ ํ
์กฐ๊ฑด๋ฌธ์ ๋ถ๊ธฐ ์์ธก์ ์ด๋ ต๊ฒ ๋ง๋ค ์ ์์ด์. ๊ฐ๋ฅํ๋ค๋ฉด ์กฐ๊ฑด๋ฌธ์ ์ ๊ฑฐํ๊ฑฐ๋ ๋จ์ํํ๋ ๊ฒ์ด ์ข๋ต๋๋ค.
์์ : ์กฐ๊ฑด๋ฌธ ์ต์ ํ
// ์กฐ๊ฑด๋ฌธ ์ฌ์ฉ
int abs_with_branch(int x) {
if (x < 0)
return -x;
else
return x;
}
// ๋นํธ ์ฐ์ฐ ์ฌ์ฉ
int abs_without_branch(int x) {
int mask = x >> 31;
return (x ^ mask) - mask;
}
'abs_without_branch' ํจ์๋ ์กฐ๊ฑด๋ฌธ ๋์ ๋นํธ ์ฐ์ฐ์ ์ฌ์ฉํด์. ์ด ๋ฐฉ์์ ๋ถ๊ธฐ ์์ธก ์คํจ๋ฅผ ์์ ๊ณ ํ์ดํ๋ผ์ธ ์คํจ์ ์ค์ฌ ์ฑ๋ฅ์ ํฅ์์ํฌ ์ ์๋ต๋๋ค. ๋ง์น ๋ง๋ฒ ๊ฐ์ฃ ? ๐งโโ๏ธโจ
5. ๋ฉ๋ชจ๋ฆฌ ํ๋ฆฌํ์นญ (Memory Prefetching)
CPU์๊ฒ ๋ฏธ๋ฆฌ ์ด๋ค ๋ฐ์ดํฐ๊ฐ ํ์ํ ์ง ์๋ ค์ฃผ๋ฉด, ์บ์ ๋ฏธ์ค๋ฅผ ์ค์ผ ์ ์์ด์. C์์๋ __builtin_prefetch
ํจ์๋ฅผ ์ฌ์ฉํ ์ ์๋ต๋๋ค.
์์ : ๋ฉ๋ชจ๋ฆฌ ํ๋ฆฌํ์นญ ์ ์ฉ
#define N 10000000
void sum_with_prefetch(int* arr, int* result) {
int sum = 0;
for (int i = 0; i < N; i++) {
__builtin_prefetch(&arr[i + 64], 0, 1); // ๋ฏธ๋ฆฌ 64๊ฐ ์์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ต๋๋ค
sum += arr[i];
}
*result = sum;
}
์ด ์์ ์์๋ ํ์ฌ ์ฒ๋ฆฌ ์ค์ธ ๋ฐ์ดํฐ๋ณด๋ค 64๊ฐ ์์ ๋ฐ์ดํฐ๋ฅผ ๋ฏธ๋ฆฌ ๊ฐ์ ธ์ค๋๋ก CPU์๊ฒ ์์ฒญํ๊ณ ์์ด์. ์ด๋ ๊ฒ ํ๋ฉด CPU๊ฐ ๋ฐ์ดํฐ๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ ์๊ฐ์ ์ค์ผ ์ ์์ด์. ๋ง์น ๋ฏธ๋๋ฅผ ๋ด๋ค๋ณด๋ ๊ฒ ๊ฐ์ฃ ? ๐ฎ๐
6. SIMD (Single Instruction, Multiple Data) ํ์ฉ
ํ๋ CPU๋ SIMD ๋ช ๋ น์ด๋ฅผ ์ง์ํด์. ์ด๋ฅผ ํ์ฉํ๋ฉด ํ ๋ฒ์ ๋ช ๋ น์ผ๋ก ์ฌ๋ฌ ๋ฐ์ดํฐ๋ฅผ ๋์์ ์ฒ๋ฆฌํ ์ ์๋ต๋๋ค.
์์ : SIMD ๋ช ๋ น์ด ์ฌ์ฉ (GCC ํ์ฅ ์ฌ์ฉ)
#include <immintrin.h>
void vector_add_simd(float* a, float* b, float* c, int n) {
for (int i = 0; i < n; i += 8) {
__m256 va = _mm256_loadu_ps(&a[i]);
__m256 vb = _mm256_loadu_ps(&b[i]);
__m256 vc = _mm256_add_ps(va, vb);
_mm256_storeu_ps(&c[i], vc);
}
}
</immintrin.h>
์ด ์ฝ๋๋ AVX2 ๋ช ๋ น์ด๋ฅผ ์ฌ์ฉํด ํ ๋ฒ์ 8๊ฐ์ float ๊ฐ์ ๋ํด์. ๋ง์น 8๊ฐ์ ์์ผ๋ก ๋์์ ์ผํ๋ ๊ฒ๊ณผ ๊ฐ์ฃ ! ๐๏ธ๐๏ธ
7. ํจ์ ์ธ๋ผ์ด๋ (Function Inlining)
์์ ํจ์๋ค์ ์ธ๋ผ์ธ์ผ๋ก ๋ง๋ค๋ฉด ํจ์ ํธ์ถ ์ค๋ฒํค๋๋ฅผ ์ค์ผ ์ ์์ด์.
์์ : ํจ์ ์ธ๋ผ์ด๋
// ์ธ๋ผ์ธ ํจ์ ์ ์
static inline int square(int x) {
return x * x;
}
// ์ฌ์ฉ ์
int sum_of_squares(int* arr, int n) {
int sum = 0;
for (int i = 0; i < n; i++) {
sum += square(arr[i]); // ์ปดํ์ผ๋ฌ๊ฐ ์ด ๋ถ๋ถ์ ์ง์ x * x๋ก ๋์ฒดํ ์ ์์ด์
}
return sum;
}
'square' ํจ์๋ฅผ ์ธ๋ผ์ธ์ผ๋ก ์ ์ํ๋ฉด, ์ปดํ์ผ๋ฌ๋ ํจ์ ํธ์ถ ๋์ ์ง์ ๊ณ์ฐ ์ฝ๋๋ฅผ ์ฝ์ ํ ์ ์์ด์. ์ด๋ ๊ฒ ํ๋ฉด ํจ์ ํธ์ถ์ ๋ฐ๋ฅธ ์ค๋ฒํค๋๋ฅผ ์์จ ์ ์๋ต๋๋ค! ๐โโ๏ธ๐จ
๐ ์ฌ๋ฅ๋ท ํ: ์ด๋ฐ ์ต์ ํ ๊ธฐ๋ฒ๋ค์ ์ค์ ํ๋ก์ ํธ์์ ํฐ ์ฐจ์ด๋ฅผ ๋ง๋ค ์ ์์ด์. ์ฌ๋ฌ๋ถ์ด ์ด๋ฐ ๊ธฐ์ ๋ค์ ์ตํ๊ณ ์ฌ๋ฅ๋ท์์ ๊ณต์ ํ๋ค๋ฉด, ๋ง์ ๊ฐ๋ฐ์๋ค์๊ฒ ๋์์ด ๋ ๊ฑฐ์์. ํนํ ์ฑ๋ฅ์ ๋ฏผ๊ฐํ ํ๋ก์ ํธ๋ฅผ ์งํํ๋ ํ๋ค์๊ฒ ํฐ ๊ฐ์น๊ฐ ์์ ๊ฑฐ๋๋๋ค!
์, ์ฌ๊ธฐ๊น์ง ์บ์ ์นํ์ ์ธ C ์ฝ๋๋ฅผ ์์ฑํ๋ ์ค์ ์์ ๋ค์ ์ดํด๋ดค์ด์. ์ด ๊ธฐ๋ฒ๋ค์ ์ ํ์ฉํ๋ฉด, ์ฌ๋ฌ๋ถ์ ํ๋ก๊ทธ๋จ์ ๋ง์น ์ํผ์นด์ฒ๋ผ ๋น ๋ฅด๊ฒ ๋ฌ๋ฆด ์ ์์ ๊ฑฐ์์! ๐๏ธ๐จ
ํ์ง๋ง ๊ธฐ์ตํ์ธ์, ์ต์ ํ๋ ํญ์ ์ธก์ ๊ณผ ํจ๊ป ์ด๋ค์ ธ์ผ ํด์. ๋ฌด์กฐ๊ฑด์ ์ธ ์ต์ ํ๋ณด๋ค๋, ์ค์ ๋ก ๋ณ๋ชฉ์ด ๋๋ ๋ถ๋ถ์ ์ฐพ์ ๊ฐ์ ํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค. ํ๋กํ์ผ๋ง ๋๊ตฌ๋ฅผ ์ฌ์ฉํด ์ฑ๋ฅ์ ์ธก์ ํ๊ณ , ์ ๋ง๋ก ๊ฐ์ ์ด ํ์ํ ๋ถ๋ถ์ ์ด๋ฐ ๊ธฐ๋ฒ๋ค์ ์ ์ฉํด๋ณด์ธ์.
์ฌ๋ฌ๋ถ, ์ด์ ์บ์์ ๋ง๋ฒ์ฌ๊ฐ ๋ ๊ฒ ๊ฐ์ ๊ธฐ๋ถ์ด ๋ค์ง ์๋์? ๐งโโ๏ธโจ ์ด ์ง์์ ๊ฐ์ง๊ณ ์ฌ๋ฌ๋ถ๋ง์ ๋ฉ์ง ํ๋ก๊ทธ๋จ์ ๋ง๋ค์ด๋ณด์ธ์. ๊ทธ๋ฆฌ๊ณ ์์ง ๋ง์ธ์, ์ฌ๋ฅ๋ท์์ ์ฌ๋ฌ๋ถ์ ๊ฒฝํ๊ณผ ์ง์์ ๊ณต์ ํ๋ฉด, ๋ ๋ง์ ๊ฐ๋ฐ์๋ค์ด ํจ๊ป ์ฑ์ฅํ ์ ์๋ต๋๋ค!
๋ค์ ์น์ ์์๋ ์ด๋ฐ ์ต์ ํ ๊ธฐ๋ฒ๋ค์ ์ค์ ํ๋ก์ ํธ์ ์ ์ฉํ ๋ ์ฃผ์ํด์ผ ํ ์ ๋ค๊ณผ ํ๋ค์ ์์๋ณผ ๊ฑฐ์์. ์ค๋น๋์ จ๋์? Let's optimize the world! ๐๐ป
๐ ์ต์ ํ ์ ์ฉ ์ ์ฃผ์์ฌํญ ๋ฐ ํ
์ฌ๋ฌ๋ถ, ์ง๊ธ๊น์ง ๋ฐฐ์ด ์บ์ ์นํ์ ์ธ ์ฝ๋ฉ ๊ธฐ๋ฒ๋ค์ ์ ๋ง ๊ฐ๋ ฅํ์ฃ ? ํ์ง๋ง ์ด๋ฐ ๊ธฐ๋ฒ๋ค์ ๋ฌด์์ ์ ์ฉํ๋ค ๋ณด๋ฉด ์คํ๋ ค ๋ฌธ์ ๊ฐ ์๊ธธ ์ ์์ด์. ๊ทธ๋์ ์ด๋ฒ์๋ ์ด๋ฐ ์ต์ ํ ๊ธฐ๋ฒ๋ค์ ์ค์ ๋ก ์ ์ฉํ ๋ ์ฃผ์ํด์ผ ํ ์ ๋ค๊ณผ ์ ์ฉํ ํ๋ค์ ์์๋ณผ ๊ฑฐ์์. ๐ง๐
1. ๊ฐ๋ ์ฑ๊ณผ ์ ์ง๋ณด์์ฑ์ ๊ณ ๋ คํ์ธ์
์ต์ ํ๋ ์ค์ํ์ง๋ง, ์ฝ๋์ ๊ฐ๋ ์ฑ๊ณผ ์ ์ง๋ณด์์ฑ์ ํฌ์ํด์๋ ์ ๋ผ์.
ํ: ์ต์ ํ๋ ์ฝ๋์ ์๋ณธ ์ฝ๋๋ฅผ ํจ๊ป ์ ์งํ๊ณ , ์ฃผ์์ผ๋ก ์ต์ ํ ์ด์ ๋ฅผ ์ค๋ช ํ์ธ์. ์ด๋ ๊ฒ ํ๋ฉด ๋์ค์ ์ฝ๋๋ฅผ ๋ณผ ๋ ์ดํดํ๊ธฐ ์ฌ์์ ธ์.
// ์๋ณธ ์ฝ๋ (์ฃผ์ ์ฒ๋ฆฌ)
/*
for (int i = 0; i < N; i++) {
result += data[i];
}
*/
// ์ต์ ํ๋ ์ฝ๋
// 4๊ฐ์ฉ ๋ฌถ์ด์ ์ฒ๋ฆฌํ์ฌ ๋ฃจํ ์ธ๋กค๋ง ์ ์ฉ
for (int i = 0; i < N; i += 4) {
result += data[i] + data[i+1] + data[i+2] + data[i+3];
}
// ๋จ์ ์์ ์ฒ๋ฆฌ
for (int i = (N/4)*4; i < N; i++) {
result += data[i];
}
2. ํ๋กํ์ผ๋ง์ ๋จผ์ ํ์ธ์
์ต์ ํํ๊ธฐ ์ ์ ํญ์ ํ๋กํ์ผ๋ง์ ํตํด ์ค์ ๋ก ๋ณ๋ชฉ์ด ๋๋ ๋ถ๋ถ์ ์ฐพ์์ผ ํด์.
ํ: gprof๋ Valgrind์ ๊ฐ์ ํ๋กํ์ผ๋ง ๋๊ตฌ๋ฅผ ์ฌ์ฉํด๋ณด์ธ์. ์ด๋ฐ ๋๊ตฌ๋ค์ ์ฌ๋ฌ๋ถ์ ํ๋ก๊ทธ๋จ์์ ๊ฐ์ฅ ์๊ฐ์ ๋ง์ด ์๋นํ๋ ๋ถ๋ถ์ ์ฐพ์์ค ๊ฑฐ์์.
3. ํ๋์จ์ด ํน์ฑ์ ๊ณ ๋ คํ์ธ์
์บ์ ํฌ๊ธฐ, CPU ์ํคํ ์ฒ ๋ฑ์ ํ๋์จ์ด๋ง๋ค ๋ค๋ฅผ ์ ์์ด์. ํน์ ํ๊ฒฝ์ ๋ง์ถ ์ต์ ํ๊ฐ ๋ค๋ฅธ ํ๊ฒฝ์์๋ ์คํ๋ ค ์ฑ๋ฅ์ ์ ํ์ํฌ ์ ์๋ต๋๋ค.
ํ: ๊ฐ๋ฅํ๋ค๋ฉด ๋ฐํ์์ ํ๋์จ์ด ํน์ฑ์ ๊ฐ์งํ๊ณ ๊ทธ์ ๋ง๋ ์ต์ ํ๋ฅผ ์ ํํ๋ ๋ฐฉ์์ ๊ณ ๋ คํด๋ณด์ธ์.
#include <cpuid.h>
int has_avx2() {
unsigned int eax, ebx, ecx, edx;
__get_cpuid(7, &eax, &ebx, &ecx, &edx);
return (ebx & bit_AVX2) != 0;
}
void vector_add(float* a, float* b, float* c, int n) {
if (has_avx2()) {
vector_add_avx2(a, b, c, n); // AVX2 ์ฌ์ฉ ๋ฒ์
} else {
vector_add_scalar(a, b, c, n); // ์ผ๋ฐ ์ค์นผ๋ผ ๋ฒ์
}
}
</cpuid.h>
4. ์ปดํ์ผ๋ฌ ์ต์ ํ๋ฅผ ํ์ฉํ์ธ์
ํ๋์ ์ปดํ์ผ๋ฌ๋ค์ ๋งค์ฐ ๊ฐ๋ ฅํ ์ต์ ํ ๊ธฐ๋ฅ์ ์ ๊ณตํด์. ๋๋ก๋ ์๋ ์ต์ ํ๋ณด๋ค ์ปดํ์ผ๋ฌ ์ต์ ํ๊ฐ ๋ ํจ๊ณผ์ ์ผ ์ ์๋ต๋๋ค.
ํ: GCC์ -O2
๋ -O3
์ต์ ํ ํ๋๊ทธ๋ฅผ ์ฌ์ฉํด๋ณด์ธ์. ํ์ง๋ง ์ฃผ์ํ์ธ์, ๋์ ์์ค์ ์ต์ ํ๋ ๊ฐ๋ ์์์น ๋ชปํ ๋์์ ์ผ์ผํฌ ์ ์์ด์.
// ์ปดํ์ผ ๋ช
๋ น์ด ์์
gcc -O3 -march=native myprogram.c -o myprogram
5. ์บ์ ๋ผ์ธ ๊ฒฝ๊ณ๋ฅผ ๊ณ ๋ คํ์ธ์
๋ฐ์ดํฐ ๊ตฌ์กฐ๋ฅผ ์ค๊ณํ ๋ ์บ์ ๋ผ์ธ ํฌ๊ธฐ(๋ณดํต 64๋ฐ์ดํธ)๋ฅผ ๊ณ ๋ คํ๋ฉด ์ข์์.
ํ: ์์ฃผ ํจ๊ป ์ ๊ทผ๋๋ ๋ฐ์ดํฐ๋ ๊ฐ์ ์บ์ ๋ผ์ธ์ ์์นํ๋๋ก ํ๊ณ , ์๋ก ๋ค๋ฅธ ์ค๋ ๋์์ ์์ฃผ ์์ ํ๋ ๋ฐ์ดํฐ๋ ๋ค๋ฅธ ์บ์ ๋ผ์ธ์ ์์นํ๋๋ก ํ์ธ์.
// ์บ์ ๋ผ์ธ์ ๊ณ ๋ คํ ๊ตฌ์กฐ์ฒด ์ค๊ณ
struct CacheAligned {
char data[64]; // ์บ์ ๋ผ์ธ ํฌ๊ธฐ๋งํผ์ ๋ฐ์ดํฐ
} __attribute__((aligned(64))); // 64๋ฐ์ดํธ ๊ฒฝ๊ณ์ ์ ๋ ฌ
6. ๊ณผ๋ํ ์ต์ ํ๋ฅผ ์ฃผ์ํ์ธ์
๋๋ก๋ '์ถฉ๋ถํ ๋น ๋ฅธ' ์ํ์์ ๋ฉ์ถ๋ ๊ฒ์ด ์ข์์. ๊ณผ๋ํ ์ต์ ํ๋ ์ฝ๋๋ฅผ ๋ณต์กํ๊ฒ ๋ง๋ค๊ณ ๋ฒ๊ทธ๋ฅผ ์ ๋ฐํ ์ ์๋ต๋๋ค.
ํ: ์ต์ ํ์ ๋ชฉํ๋ฅผ ๋ช ํํ ์ ํ๊ณ , ๊ทธ ๋ชฉํ์ ๋๋ฌํ๋ฉด ๋ฉ์ถ์ธ์. ์๋ฒฝ๋ณด๋ค๋ '์ถฉ๋ถํ ์ข์' ์ํ๋ฅผ ๋ชฉํ๋ก ํ์ธ์.
7. ๋ฉํฐ์ค๋ ๋ฉ ํ๊ฒฝ์ ๊ณ ๋ คํ์ธ์
์บ์ ์ต์ ํ ๊ธฐ๋ฒ ์ค ์ผ๋ถ๋ ๋ฉํฐ์ค๋ ๋ฉ ํ๊ฒฝ์์ ๋ฌธ์ ๋ฅผ ์ผ์ผํฌ ์ ์์ด์. ํนํ false sharing์ ์ฃผ์ํด์ผ ํด์.
ํ: ๋ฉํฐ์ค๋ ๋ ํ๊ฒฝ์์๋ ๊ฐ ์ค๋ ๋๊ฐ ์ฌ์ฉํ๋ ๋ฐ์ดํฐ๋ฅผ ์บ์ ๋ผ์ธ ๋จ์๋ก ๋ถ๋ฆฌํ๋ ๊ฒ์ด ์ข์์.
// False sharing์ ํผํ๊ธฐ ์ํ ๊ตฌ์กฐ์ฒด ์ค๊ณ
struct ThreadData {
int data;
char padding[60]; // ์บ์ ๋ผ์ธ์ ๋๋จธ์ง ๋ถ๋ถ์ ์ฑ์
} __attribute__((aligned(64)));
8. ์ต์ ํ ๊ฒฐ๊ณผ๋ฅผ ํญ์ ์ธก์ ํ์ธ์
์ต์ ํ๋ฅผ ์ ์ฉํ ํ์๋ ๋ฐ๋์ ์ฑ๋ฅ ํฅ์์ ์ธก์ ํด์ผ ํด์. ๋๋ก๋ ์์๊ณผ ๋ค๋ฅธ ๊ฒฐ๊ณผ๊ฐ ๋์ฌ ์ ์๋ต๋๋ค.
ํ: ๋ฒค์น๋งํน ๋๊ตฌ๋ฅผ ์ฌ์ฉํด ์ต์ ํ ์ ํ์ ์ฑ๋ฅ์ ์ ํํ ๋น๊ตํ์ธ์. ์์ ํ ์คํธ ์ผ์ด์ค๋ฟ๋ง ์๋๋ผ ์ค์ ์ฌ์ฉ ํ๊ฒฝ๊ณผ ์ ์ฌํ ๋๊ท๋ชจ ๋ฐ์ดํฐ๋ก๋ ํ ์คํธํด๋ณด์ธ์.
#include <time.h>
clock_t start, end;
double cpu_time_used;
start = clock();
// ์ธก์ ํ ์ฝ๋
end = clock();
cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC;
printf("์คํ ์๊ฐ: %f ์ด\n", cpu_time_used);
</time.h>
๐ ์ฌ๋ฅ๋ท ํ: ์ต์ ํ ๊ณผ์ ์์ ์ป์ ์ธ์ฌ์ดํธ์ ๊ฒฝํ์ ์ฌ๋ฅ๋ท์์ ๊ณต์ ํด๋ณด์ธ์. ์ฌ๋ฌ๋ถ์ด ๊ฒช์ ์ํ์ฐฉ์ค์ ์ฑ๊ณต ์ฌ๋ก๋ ๋ค๋ฅธ ๊ฐ๋ฐ์๋ค์๊ฒ ํฐ ๋์์ด ๋ ๊ฑฐ์์. ํนํ ํน์ ๋๋ฉ์ธ์ด๋ ํ๊ฒฝ์์์ ์ต์ ํ ๊ฒฝํ์ ๋งค์ฐ ๊ฐ์น ์๋ ์ ๋ณด๊ฐ ๋ ์ ์๋ต๋๋ค!
์, ์ฌ๋ฌ๋ถ! ์ด์ ์บ์ ์นํ์ ์ธ C ์ฝ๋๋ฅผ ์์ฑํ๋ ๋ฐฉ๋ฒ๋ฟ๋ง ์๋๋ผ, ๊ทธ๊ฒ์ ์ค์ ๋ก ์ ์ฉํ ๋ ์ฃผ์ํด์ผ ํ ์ ๋ค๋ ์๊ฒ ๋์์ด์. ์ด ์ง์๋ค์ ์ ํ์ฉํ๋ฉด, ์ฌ๋ฌ๋ถ์ ์ฑ๋ฅ์ ๋ง๋ฒ์ฌ๊ฐ ๋ ์ ์์ ๊ฑฐ์์! ๐งโโ๏ธโจ
ํ์ง๋ง ๊ธฐ์ตํ์ธ์. ์ต์ ํ๋ ํญ์ ์ธก์ , ๋ถ์, ๊ฐ์ , ๊ฒ์ฆ์ ์ํ ๊ณผ์ ์ ๊ฑฐ์ณ์ผ ํด์. ๊ทธ๋ฆฌ๊ณ ๋๋ก๋ '์ต์ ํํ์ง ์๋ ๊ฒ'์ด ์ต์ ์ ์ต์ ํ์ผ ์ ์๋ต๋๋ค. ์ฝ๋์ ๋ช ํ์ฑ๊ณผ ์ ์ง๋ณด์์ฑ์ ํด์น์ง ์๋ ์ ์์, ๊ผญ ํ์ํ ๊ณณ์ ์ต์ ํ๋ฅผ ์ ์ฉํ์ธ์.
์ฌ๋ฌ๋ถ์ ์ฝ๋๊ฐ ๋น์ ์๋๋ก ๋ฌ๋ฆฌ๊ธธ ๋ฐ๋๊ฒ์! ๊ทธ๋ฆฌ๊ณ ์ฌ๋ฌ๋ถ์ด ์ป์ ๊ท์คํ ๊ฒฝํ๋ค์ ์ฌ๋ฅ๋ท์์ ๋ค๋ฅธ ๊ฐ๋ฐ์๋ค๊ณผ ๋๋๋ ๊ฒ๋ ์์ง ๋ง์ธ์. ํจ๊ป ์ฑ์ฅํ๋ ๊ฐ๋ฐ์ ์ปค๋ฎค๋ํฐ๋ฅผ ๋ง๋ค์ด๊ฐ์! ๐๐จโ๐ป๐ฉโ๐ป
- ์ง์์ธ์ ์ฒ - ์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
- ์ ์๊ถ ๋ฐ ์์ ๊ถ: ๋ณธ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ๋ ์ AI ๊ธฐ์ ๋ก ์์ฑ๋์์ผ๋ฉฐ, ๋ํ๋ฏผ๊ตญ ์ ์๊ถ๋ฒ ๋ฐ ๊ตญ์ ์ ์๊ถ ํ์ฝ์ ์ํด ๋ณดํธ๋ฉ๋๋ค.
- AI ์์ฑ ์ปจํ ์ธ ์ ๋ฒ์ ์ง์: ๋ณธ AI ์์ฑ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ์ง์ ์ฐฝ์๋ฌผ๋ก ์ธ์ ๋๋ฉฐ, ๊ด๋ จ ๋ฒ๊ท์ ๋ฐ๋ผ ์ ์๊ถ ๋ณดํธ๋ฅผ ๋ฐ์ต๋๋ค.
- ์ฌ์ฉ ์ ํ: ์ฌ๋ฅ๋ท์ ๋ช ์์ ์๋ฉด ๋์ ์์ด ๋ณธ ์ปจํ ์ธ ๋ฅผ ๋ณต์ , ์์ , ๋ฐฐํฌ, ๋๋ ์์ ์ ์ผ๋ก ํ์ฉํ๋ ํ์๋ ์๊ฒฉํ ๊ธ์ง๋ฉ๋๋ค.
- ๋ฐ์ดํฐ ์์ง ๊ธ์ง: ๋ณธ ์ปจํ ์ธ ์ ๋ํ ๋ฌด๋จ ์คํฌ๋ํ, ํฌ๋กค๋ง, ๋ฐ ์๋ํ๋ ๋ฐ์ดํฐ ์์ง์ ๋ฒ์ ์ ์ฌ์ ๋์์ด ๋ฉ๋๋ค.
- AI ํ์ต ์ ํ: ์ฌ๋ฅ๋ท์ AI ์์ฑ ์ปจํ ์ธ ๋ฅผ ํ AI ๋ชจ๋ธ ํ์ต์ ๋ฌด๋จ ์ฌ์ฉํ๋ ํ์๋ ๊ธ์ง๋๋ฉฐ, ์ด๋ ์ง์ ์ฌ์ฐ๊ถ ์นจํด๋ก ๊ฐ์ฃผ๋ฉ๋๋ค.
์ฌ๋ฅ๋ท์ ์ต์ AI ๊ธฐ์ ๊ณผ ๋ฒ๋ฅ ์ ๊ธฐ๋ฐํ์ฌ ์์ฌ์ ์ง์ ์ฌ์ฐ๊ถ์ ์ ๊ทน์ ์ผ๋ก ๋ณดํธํ๋ฉฐ,
๋ฌด๋จ ์ฌ์ฉ ๋ฐ ์นจํด ํ์์ ๋ํด ๋ฒ์ ๋์์ ํ ๊ถ๋ฆฌ๋ฅผ ๋ณด์ ํฉ๋๋ค.
ยฉ 2025 ์ฌ๋ฅ๋ท | All rights reserved.
๋๊ธ 0๊ฐ