[ํŒŒ์ด์ฌ] Multiprocessing, Multithreading ์ž์› ๋ถ„ํ•  ๋ฐ ํ• ๋‹น

Posted by Euisuk's Dev Log on February 19, 2024

[ํŒŒ์ด์ฌ] Multiprocessing, Multithreading ์ž์› ๋ถ„ํ•  ๋ฐ ํ• ๋‹น

์›๋ณธ ๊ฒŒ์‹œ๊ธ€: https://velog.io/@euisuk-chung/ํŒŒ์ด์ฌ-Multiprocessing-Multithreading-์ž์›-๋ถ„ํ• -๋ฐ-ํ• ๋‹น

๋ฉ€ํ‹ฐํ”„๋กœ์„ธ์‹ฑ๊ณผ ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋”ฉ์—์„œ ์ž์› ๋ถ„ํ• ๊ณผ ์ž‘์—… ํ• ๋‹น์€ ๊ฐ๊ฐ ๋‹ค๋ฅด๊ฒŒ ์ด๋ฃจ์–ด์ง‘๋‹ˆ๋‹ค. ์ด ๊ณผ์ •์„ ์ดํ•ดํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋จผ์ €, ์ปดํ“จํ„ฐ์˜ ์ž์›(ํŠนํžˆ CPU์™€ ๋ฉ”๋ชจ๋ฆฌ) ์‚ฌ์šฉ ๋ฐฉ์‹๊ณผ ์ž‘์—…์˜ ์ข…๋ฅ˜(์˜ˆ: CPU ์ง‘์•ฝ์  vs. I/O ์ง‘์•ฝ์ )๋ฅผ ๊ณ ๋ คํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋ฉ€ํ‹ฐํ”„๋กœ์„ธ์‹ฑ(Multiprocessing)์˜ ์ž์› ๋ถ„ํ• 

๋ฉ€ํ‹ฐํ”„๋กœ์„ธ์‹ฑ์—์„œ๋Š” ๊ฐ ํ”„๋กœ์„ธ์Šค๊ฐ€ ๋…๋ฆฝ๋œ ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„์„ ๊ฐ€์ง‘๋‹ˆ๋‹ค. ์ด๋Š” ๊ฐ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์‹œ์Šคํ…œ์˜ ์ž์›์„ ๋…๋ฆฝ์ ์œผ๋กœ ํ• ๋‹น๋ฐ›๋Š”๋‹ค๋Š” ์˜๋ฏธ์ž…๋‹ˆ๋‹ค. CPU ์ž์›์˜ ๋ถ„ํ• ์€ ์šด์˜ ์ฒด์ œ์˜ ์Šค์ผ€์ค„๋Ÿฌ์— ์˜ํ•ด ๊ด€๋ฆฌ๋˜๋ฉฐ, ์—ฌ๋Ÿฌ ํ”„๋กœ์„ธ์Šค ๊ฐ„์— CPU ์‹œ๊ฐ„์„ ๊ณต์ •ํ•˜๊ฒŒ ๋ถ„๋ฐฐํ•ฉ๋‹ˆ๋‹ค.

์ž‘์—…์ด N๊ฐœ์˜ ํ”„๋กœ์„ธ์Šค์— ๋ถ„๋ฐฐ๋  ๋•Œ, ์ด๋ก ์ ์œผ๋กœ๋Š” ๊ฐ ํ”„๋กœ์„ธ์Šค์— ์ž‘์—…์˜ 1/N์„ ํ• ๋‹นํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์‹ค์ œ ๋ถ„ํ• ์€ ์ž‘์—…์˜ ์„ฑ๊ฒฉ, ํ”„๋กœ์„ธ์Šค์˜ ์‹คํ–‰ ์ƒํƒœ, ์‹œ์Šคํ…œ์˜ ๋‹ค๋ฅธ ์š”๊ตฌ ์‚ฌํ•ญ ๋“ฑ์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์–ด๋–ค ํ”„๋กœ์„ธ์Šค๋Š” CPU๋ฅผ ๋งŽ์ด ์‚ฌ์šฉํ•˜๋Š” ๋ฐ˜๋ฉด, ๋‹ค๋ฅธ ํ”„๋กœ์„ธ์Šค๋Š” ๋Œ€๊ธฐ ์ƒํƒœ์— ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฉ€ํ‹ฐ์Šค๋ ˆ๋”ฉ(Multithreading)์˜ ์ž์› ๋ถ„ํ• 

๋ฉ€ํ‹ฐ์Šค๋ ˆ๋”ฉ์—์„œ๋Š” ๋ชจ๋“  ์Šค๋ ˆ๋“œ๊ฐ€ ํ”„๋กœ์„ธ์Šค์˜ ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„์„ ๊ณต์œ ํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ, ๋ฉ”๋ชจ๋ฆฌ ์ž์›์€ ๋ณ„๋„๋กœ ๋ถ„ํ• ๋˜์ง€ ์•Š๊ณ , ๋ชจ๋“  ์Šค๋ ˆ๋“œ๊ฐ€ ๊ฐ™์€ ๋ฉ”๋ชจ๋ฆฌ ์˜์—ญ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. CPU ์ž์›์˜ ๊ฒฝ์šฐ, ์šด์˜ ์ฒด์ œ์˜ ์Šค๋ ˆ๋“œ ์Šค์ผ€์ค„๋Ÿฌ๊ฐ€ ๊ฐ ์Šค๋ ˆ๋“œ์— CPU ์‹œ๊ฐ„์„ ํ• ๋‹นํ•ฉ๋‹ˆ๋‹ค.

์Šค๋ ˆ๋“œ ๊ฐ„์˜ ์ž‘์—… ๋ถ„ํ• ์€ ํ”„๋กœ์„ธ์Šค ๋‚ด์—์„œ ์ด๋ฃจ์–ด์ง€๋ฉฐ, ์Šค๋ ˆ๋“œ๊ฐ€ ์ˆ˜ํ–‰ํ•˜๋Š” ์ž‘์—…์€ ์ผ๋ฐ˜์ ์œผ๋กœ ๋” ์ž‘๊ณ , ๊ตฌ์ฒด์ ์ธ ์ž‘์—… ๋‹จ์œ„๋กœ ๋‚˜๋ˆ„์–ด์ง‘๋‹ˆ๋‹ค. ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋”ฉ ํ™˜๊ฒฝ์—์„œ๋Š” I/O ์ž‘์—…์ด ์ง„ํ–‰๋˜๋Š” ๋™์•ˆ ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ๊ฐ€ CPU๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด, ์ „์ฒด์ ์ธ ํ”„๋กœ๊ทธ๋žจ์˜ ํšจ์œจ์„ฑ์„ ๋†’์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

โญ (Q&A) ์—ฌ๊ธฐ์„œ ์ž ๊น!!

Q. ๋ฉ€ํ‹ฐํ”„๋กœ์„ธ์Šค์—์„œ ํ”„๋กœ์„ธ์ŠคA์™€ ํ”„๋กœ์„ธ์ŠคB๊ฐ€ ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿผ 4์ด๋ผ๋Š” ๊ฐ€์šฉ ์ž์›์ด ์žˆ์„๋•Œ ๋งŒ์•ฝ ํ”„๋กœ์„ธ์ŠคA๊ฐ€ ๋จผ์ € ๋๋‚˜๋ฉด ๋‚˜๋จธ์ง€ ํ”„๋กœ์„ธ์Šค์ธ ํ”„๋กœ์„ธ์ŠคB๊ฐ€ ๋‚จ์€ ์ž์› 4๊ฐœ๋ฅผ ๋‹ค ์“ฐ๋„๋ก ๋ฐ”๋€Œ๋„๋ก ์ž๋™์œผ๋กœ ํ• ๋‹นํ•ด์ฃผ๋‚˜์š”?

A. ์‹ค์ œ๋กœ ํ”„๋กœ์„ธ์ŠคA๊ฐ€ ์ข…๋ฃŒ๋˜์–ด ์ž์›์ด ๋ฐ˜ํ™˜๋  ๋•Œ, ํ”„๋กœ์„ธ์ŠคB๊ฐ€ ์ž๋™์œผ๋กœ ๋ชจ๋“  ์ž์›์„ ํ™œ์šฉํ•˜๋„๋ก ์‹œ์Šคํ…œ์ด ์žฌ์กฐ์ •๋˜๋Š” ๊ฒƒ์€ ๋ณด์žฅ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ž์›์˜ ์žฌํ• ๋‹น์€ ์šด์˜ ์ฒด์ œ์˜ ์Šค์ผ€์ค„๋ง ์•Œ๊ณ ๋ฆฌ์ฆ˜๊ณผ ์ •์ฑ…์— ๋”ฐ๋ผ ๊ฒฐ์ •๋˜๋ฉฐ, ๋‹ค๋ฅธ ๋Œ€๊ธฐ ์ค‘์ธ ํ”„๋กœ์„ธ์Šค๋‚˜ ์‹œ์Šคํ…œ์˜ ์ „๋ฐ˜์ ์ธ ์ž์› ๊ด€๋ฆฌ ์ „๋žต์— ์˜ํ•ด ์˜ํ–ฅ์„ ๋ฐ›์Šต๋‹ˆ๋‹ค. ํ”„๋กœ์„ธ์ŠคB๊ฐ€ ์ถ”๊ฐ€ ์ž์›์„ ํ™œ์šฉํ•˜๋ ค๋ฉด, ํ•ด๋‹น ํ”„๋กœ์„ธ์Šค๊ฐ€ ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ๋ฅผ ์ง€์›ํ•˜๊ณ  ์ถ”๊ฐ€ CPU ์ฝ”์–ด๋ฅผ ํšจ์œจ์ ์œผ๋กœ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ตฌ์กฐ๋กœ ์„ค๊ณ„๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

โญ ์ถ”๊ฐ€ ์„ค๋ช…: ์ž์› ํ• ๋‹น์˜ ๋™์ž‘ ๋ฐฉ์‹

โœ… CPU ์ฝ”์–ด ํ• ๋‹น: ๊ฐ€์šฉ ์ž์›์ด CPU ์ฝ”์–ด๋ผ๊ณ  ํ•  ๋•Œ, ๊ฐ ํ”„๋กœ์„ธ์Šค๋Š” ์šด์˜ ์ฒด์ œ์— ์˜ํ•ด ํ•˜๋‚˜ ์ด์ƒ์˜ CPU ์ฝ”์–ด์— ํ• ๋‹น๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ”„๋กœ์„ธ์ŠคA์™€ ํ”„๋กœ์„ธ์ŠคB๊ฐ€ ๊ฐ๊ฐ 2๊ฐœ์˜ CPU ์ฝ”์–ด๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค๋ฉด, ์ด๋Š” ํ”„๋กœ์„ธ์Šค๊ฐ€ ์‹คํ–‰๋˜๋Š” ๋™์•ˆ ๋™์‹œ์— 2๊ฐœ์˜ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Œ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

โœ… ๋™์  ์žฌํ• ๋‹น: ํ”„๋กœ์„ธ์ŠคA๊ฐ€ ์ž‘์—…์„ ์™„๋ฃŒํ•˜๊ณ  ์ข…๋ฃŒ๋˜๋ฉด, ๊ทธ ํ”„๋กœ์„ธ์Šค์— ํ• ๋‹น๋˜์—ˆ๋˜ ์ž์›(์—ฌ๊ธฐ์„œ๋Š” CPU ์ฝ”์–ด)์€ ์‹œ์Šคํ…œ์— ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค. ์ดํ›„ ์šด์˜ ์ฒด์ œ์˜ ์Šค์ผ€์ค„๋Ÿฌ๋Š” ์ด์ œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ž์›์„ ๋‹ค์‹œ ๋ถ„๋ฐฐํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ, ์ž๋™์œผ๋กœ ํ”„๋กœ์„ธ์ŠคB๊ฐ€ ๋‚˜๋จธ์ง€ ์ž์›์„ ๋ชจ๋‘ ์‚ฌ์šฉํ•˜๋„๋ก ํ• ๋‹น๋ฐ›๋Š” ๊ฒƒ์€ ์ž๋™์œผ๋กœ ์ด๋ฃจ์–ด์ง€์ง€ ์•Š์Šต๋‹ˆ๋‹ค. โœ… ์ž์›์˜ ์žฌํ• ๋‹น ์กฐ๊ฑด: ํ”„๋กœ์„ธ์ŠคB๊ฐ€ ์ถ”๊ฐ€์ ์ธ CPU ์ฝ”์–ด๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜๋Š”์ง€ ์—ฌ๋ถ€๋Š” ์—ฌ๋Ÿฌ ์š”์†Œ์— ์˜ํ•ด ๊ฒฐ์ •๋ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์šด์˜ ์ฒด์ œ์˜ ์Šค์ผ€์ค„๋ง ์ •์ฑ…, ํ”„๋กœ์„ธ์Šค์˜ ์šฐ์„ ์ˆœ์œ„, ๊ทธ๋ฆฌ๊ณ  ํ”„๋กœ์„ธ์ŠคB๊ฐ€ ์ถ”๊ฐ€ ์ž์›์„ ํšจ๊ณผ์ ์œผ๋กœ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋Š”์ง€(์˜ˆ: ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•œ ์ž‘์—…์ธ์ง€)์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. โœ… ์ž์› ์‚ฌ์šฉ์˜ ์ตœ์ ํ™”: ๋Œ€๋ถ€๋ถ„์˜ ํ˜„๋Œ€ ์šด์˜ ์ฒด์ œ๋Š” ์‹œ์Šคํ…œ ์ž์›์„ ํšจ์œจ์ ์œผ๋กœ ํ™œ์šฉํ•˜๊ธฐ ์œ„ํ•œ ๋ณต์žกํ•œ ์Šค์ผ€์ค„๋ง ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ํ”„๋กœ์„ธ์ŠคA๊ฐ€ ์ข…๋ฃŒ๋˜์–ด ์ž์›์ด ๋ฐ˜ํ™˜๋˜๋ฉด, ์ด ์ž์›์€ ์‹œ์Šคํ…œ์˜ ๋‹ค๋ฅธ ๋Œ€๊ธฐ ์ค‘์ธ ํ”„๋กœ์„ธ์Šค์— ํ• ๋‹น๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜, ํŠน์ • ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ž๋™์œผ๋กœ ๋ชจ๋“  ๊ฐ€์šฉ ์ž์›์„ ๋…์ ํ•˜๋„๋ก ์‹œ์Šคํ…œ์ด ์žฌ์กฐ์ •ํ•˜๋Š” ๊ฒƒ์€ ์ผ๋ฐ˜์ ์ธ ๊ฒฝ์šฐ๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค.


์ž‘์—… ํ• ๋‹น ๋ฐฉ์‹

์‹ค์ œ ์ž‘์—… ํ• ๋‹น์€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋ ˆ๋ฒจ์—์„œ ๊ฐœ๋ฐœ์ž๊ฐ€ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค. ๋ฉ€ํ‹ฐํ”„๋กœ์„ธ์‹ฑ์ด๋‚˜ ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋”ฉ์„ ์‚ฌ์šฉํ•  ๋•Œ, ๊ฐ๊ฐ์˜ ํ”„๋กœ์„ธ์Šค๋‚˜ ์Šค๋ ˆ๋“œ์— ํ• ๋‹นํ•  ์ž‘์—…์˜ ํฌ๊ธฐ์™€ ๋ฒ”์œ„๋Š” ํ”„๋กœ๊ทธ๋žจ์˜ ๊ตฌ์กฐ์™€ ์š”๊ตฌ ์‚ฌํ•ญ์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง‘๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ์ž‘์—…์„ ์—ฌ๋Ÿฌ ํ”„๋กœ์„ธ์Šค์— ๋ถ„๋ฐฐํ•  ๋•Œ๋Š” ๊ฐ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ฒ˜๋ฆฌํ•  ๋ฐ์ดํ„ฐ์˜ ์–‘์„ ๊ท ๋“ฑํ•˜๊ฒŒ ๋‚˜๋ˆ„๊ฑฐ๋‚˜, ํŠน์ • ์กฐ๊ฑด์— ๋งž๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ํ• ๋‹นํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ๋ถ„ํ• ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฉ€ํ‹ฐํ”„๋กœ์„ธ์‹ฑ๊ณผ ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋”ฉ ๋ชจ๋‘ ์ž‘์—…์˜ ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ๋ฅผ ํ†ตํ•ด ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ์‹œํ‚ค์ง€๋งŒ, ๊ทธ ๊ตฌํ˜„ ๋ฐฉ์‹๊ณผ ์‚ฌ์šฉ ์‚ฌ๋ก€๋Š” ํฌ๊ฒŒ ๋‹ค๋ฆ…๋‹ˆ๋‹ค. ๋ฉ€ํ‹ฐํ”„๋กœ์„ธ์‹ฑ์€ ๋…๋ฆฝ์ ์ธ ์ž‘์—…์ด ๋งŽ๊ณ , ๊ฐ ์ž‘์—…์ด ์ƒ๋‹นํ•œ ์–‘์˜ CPU ์ž์›์„ ํ•„์š”๋กœ ํ•  ๋•Œ ์œ ๋ฆฌํ•˜๋ฉฐ, ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋”ฉ์€ ์ž‘์—… ๊ฐ„์— ์ž์›์„ ๊ณต์œ ํ•ด์•ผ ํ•˜๊ฑฐ๋‚˜ I/O ๋ฐ”์šด๋“œ ์ž‘์—…์ด ๋งŽ์„ ๋•Œ ํšจ๊ณผ์ ์ž…๋‹ˆ๋‹ค.

์ž‘์—… ํ• ๋‹น๊ณผ ์ž์› ๋ถ„๋ฐฐ ๋ฐฉ์‹์— ๋Œ€ํ•ด ๋” ์ž์„ธํžˆ ์„ค๋ช…ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ, ๋ฉ€ํ‹ฐํ”„๋กœ์„ธ์‹ฑ๊ณผ ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋”ฉ ํ™˜๊ฒฝ์—์„œ์˜ ์ž์› ํ• ๋‹น์€ ์ž๋™๊ณผ ์ˆ˜๋™(๊ฐœ๋ฐœ์ž ์ง€์ •) ๋ฐฉ์‹์„ ๋ชจ๋‘ ํฌํ•จํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ž๋™ ํ• ๋‹น(์‹œ์Šคํ…œ)

  • ๊ฐ€์šฉ ์ž์›์˜ ์ž๋™ ๋ถ„๋ฐฐ: ์šด์˜ ์ฒด์ œ์˜ ์Šค์ผ€์ค„๋Ÿฌ๊ฐ€ ํ”„๋กœ์„ธ์Šค๋‚˜ ์Šค๋ ˆ๋“œ์— ๋Œ€ํ•ด CPU ์‹œ๊ฐ„์„ ์ž๋™์œผ๋กœ ํ• ๋‹นํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ, ์Šค์ผ€์ค„๋Ÿฌ๋Š” ์‹œ์Šคํ…œ์˜ ํ˜„์žฌ ๋ถ€ํ•˜, ํ”„๋กœ์„ธ์Šค์˜ ์šฐ์„ ์ˆœ์œ„, ํ”„๋กœ์„ธ์Šค์˜ ์ƒํƒœ(์‹คํ–‰ ์ค‘, ๋Œ€๊ธฐ ์ค‘ ๋“ฑ)์™€ ๊ฐ™์€ ์—ฌ๋Ÿฌ ์š”์ธ์„ ๊ณ ๋ คํ•˜์—ฌ ์ž์›์„ ๋ถ„๋ฐฐํ•ฉ๋‹ˆ๋‹ค. ๋””ํดํŠธ๋กœ, ์‹œ์Šคํ…œ์€ ๊ฐ€๋Šฅํ•œ ๊ณต์ •ํ•˜๊ฒŒ ์ž์›์„ ๋ถ„๋ฐฐํ•˜๋ ค๊ณ  ์‹œ๋„ํ•˜์ง€๋งŒ, ์ด๋Š” โ€œ1/Nโ€์ด๋ผ๋Š” ๊ณ ์ • ๋น„์œจ๋กœ ์ •ํ™•ํžˆ ๋ถ„๋ฐฐ๋œ๋‹ค๋Š” ์˜๋ฏธ๋Š” ์•„๋‹™๋‹ˆ๋‹ค.

์ˆ˜๋™ ํ• ๋‹น(๊ฐœ๋ฐœ์ž ์ง€์ •)

  • ๊ฐœ๋ฐœ์ž์— ์˜ํ•œ ๋ช…์‹œ์  ๋ถ„๋ฐฐ: ๊ฐœ๋ฐœ์ž๋Š” ํ”„๋กœ๊ทธ๋žจ์˜ ์š”๊ตฌ ์‚ฌํ•ญ๊ณผ ์ž‘์—…์˜ ํŠน์„ฑ์„ ๊ณ ๋ คํ•˜์—ฌ, ๊ฐ ํ”„๋กœ์„ธ์Šค๋‚˜ ์Šค๋ ˆ๋“œ์— ํ• ๋‹น๋  ์ž‘์—…์˜ ์–‘์ด๋‚˜ ์ž์›์˜ ์‚ฌ์šฉ์„ ๋ช…์‹œ์ ์œผ๋กœ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ์ž‘์—…์„ ์—ฌ๋Ÿฌ ํ”„๋กœ์„ธ์Šค์— ๋ถ„๋ฐฐํ•  ๋•Œ ํŠน์ • ๊ธฐ์ค€์— ๋”ฐ๋ผ ์ž‘์—…์„ ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ด๋Š” ์ž‘์—…์˜ ํšจ์œจ์„ฑ๊ณผ ์‹คํ–‰ ์‹œ๊ฐ„์— ์˜ํ–ฅ์„ ๋ฏธ์น  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฉ€ํ‹ฐํ”„๋กœ์„ธ์‹ฑ ์ž์› ํ• ๋‹น ์˜ˆ์‹œ

์ด ์˜ˆ์‹œ์—์„œ๋Š” ๋Œ€๋Ÿ‰์˜ ๋ฐ์ดํ„ฐ๋ฅผ 4๊ฐœ์˜ ์ฒญํฌ๋กœ ๋‚˜๋ˆ„๊ณ , ๊ฐ ์ฒญํฌ๋ฅผ ๋ณ„๋„์˜ ํ”„๋กœ์„ธ์Šค์— ํ• ๋‹นํ•˜์—ฌ ๋ณ‘๋ ฌ๋กœ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ์ž‘์—…์˜ ๋ถ„๋ฐฐ๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ์ง€์ •ํ•œ ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค.

1
2
3
4
5
6
7
8
9
10
11
12
13
from multiprocessing import Pool

def my_task(data_chunk):
    # ๋ณต์žกํ•œ ๊ณ„์‚ฐ ์ˆ˜ํ–‰
    result = sum(data_chunk)
    return result

if __name__ == "__main__":
    data = range(1000000)  # ๋Œ€๋Ÿ‰์˜ ๋ฐ์ดํ„ฐ
    chunks = [data[i::4] for i in range(4)]  # ๋ฐ์ดํ„ฐ๋ฅผ 4๊ฐœ์˜ ์ฒญํฌ๋กœ ๋‚˜๋ˆ”

    with Pool(4) as p:  # 4๊ฐœ์˜ ํ”„๋กœ์„ธ์Šค ํ’€ ์ƒ์„ฑ
        results = p.map(my_task, chunks)  # ๊ฐ ์ฒญํฌ๋ฅผ ๋ณ„๋„์˜ ํ”„๋กœ์„ธ์Šค์— ํ• ๋‹น

์œ„ ํŒŒ์ด์ฌ ์ฝ”๋“œ์—์„œ multiprocessing.Pool์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฉ€ํ‹ฐํ”„๋กœ์„ธ์‹ฑ์„ ๊ตฌํ˜„ํ•  ๋•Œ, ์ž์› ํ• ๋‹น์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ด๋ฃจ์–ด์ง‘๋‹ˆ๋‹ค:

ํ”„๋กœ์„ธ์Šค ํ’€๊ณผ CPU ์ฝ”์–ด ํ• ๋‹น

  • ํ”„๋กœ์„ธ์Šค ํ’€ ์ƒ์„ฑ: Pool(4)์— ์˜ํ•ด 4๊ฐœ์˜ ๋ณ„๋„ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค. ์ด๋Š” ๋ฉ€ํ‹ฐํ”„๋กœ์„ธ์‹ฑ์„ ์œ„ํ•œ ํ”„๋กœ์„ธ์Šค ํ’€๋กœ, ๋ณ‘๋ ฌ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์œ„ํ•ด ์ค€๋น„๋œ ํ”„๋กœ์„ธ์Šค ์ง‘ํ•ฉ์ž…๋‹ˆ๋‹ค.
  • CPU ์ฝ”์–ด ์‚ฌ์šฉ: ์‹œ์Šคํ…œ์— 8๊ฐœ์˜ CPU ์ฝ”์–ด๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ, Pool(4)์— ์˜ํ•ด ์ƒ์„ฑ๋œ ๊ฐ ํ”„๋กœ์„ธ์Šค๋Š” ์ด์šฉ ๊ฐ€๋Šฅํ•œ CPU ์ฝ”์–ด ์ค‘ ํ•˜๋‚˜๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ ์ค‘์š”ํ•œ ์ ์€, ํ”„๋กœ์„ธ์Šค ํ’€์— ์˜ํ•ด ์ƒ์„ฑ๋œ ํ”„๋กœ์„ธ์Šค ์ˆ˜๊ฐ€ ์‹œ์Šคํ…œ์˜ CPU ์ฝ”์–ด ์ˆ˜๋ณด๋‹ค ์ ๊ธฐ ๋•Œ๋ฌธ์—, ๋ชจ๋“  ํ”„๋กœ์„ธ์Šค๊ฐ€ ๋™์‹œ์— ์‹คํ–‰๋  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๊ฐ๊ฐ ๋ณ„๋„์˜ CPU ์ฝ”์–ด์— ํ• ๋‹น๋  ๊ฐ€๋Šฅ์„ฑ์ด ๋†’์Šต๋‹ˆ๋‹ค.

์ž‘์—… ์ฒ˜๋ฆฌ ๋ฐฉ์‹

  • ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ: ์ƒ์„ฑ๋œ 4๊ฐœ์˜ ํ”„๋กœ์„ธ์Šค๋Š” ๋™์‹œ์— ์‹คํ–‰๋˜์–ด ๊ฐ๊ฐ ํ• ๋‹น๋œ ์ž‘์—…(๋ฐ์ดํ„ฐ ์ฒญํฌ)์„ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ์‹œ์Šคํ…œ์— ์—ฌ์œ  ์ฝ”์–ด๊ฐ€ ์ถฉ๋ถ„ํžˆ ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ์ด ํ”„๋กœ์„ธ์Šค๋“ค์€ ์„œ๋กœ ๊ฒฝ์Ÿ ์—†์ด ๊ฐ์ž์˜ ์ฝ”์–ด์—์„œ ์‹คํ–‰๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์ž์› ํ™œ์šฉ ์ตœ์ ํ™”: 8๊ฐœ์˜ ์ฝ”์–ด ์ค‘ 4๊ฐœ๋งŒ ์‚ฌ์šฉ๋˜๋ฏ€๋กœ, ๋‚˜๋จธ์ง€ ์ฝ”์–ด๋Š” ์‹œ์Šคํ…œ์˜ ๋‹ค๋ฅธ ํ”„๋กœ์„ธ์Šค๋‚˜ ์ž‘์—…์— ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ๋ฉ€ํ‹ฐํƒœ์Šคํ‚น ํ™˜๊ฒฝ์—์„œ ์‹œ์Šคํ…œ ์ž์›์„ ํšจ์œจ์ ์œผ๋กœ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค.

(์ฐธ๊ณ ) ๊ทธ๋Ÿผ ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ๊ฐ€์šฉ ์ž์›์„ ๋‹ค ์“ธ ์ˆ˜ ์žˆ์„๊นŒ?

ํŒŒ์ด์ฌ์˜ multiprocessing ๋ชจ๋“ˆ์€ ํ”„๋กœ์„ธ์Šค๋‹น CPU ์ฝ”์–ด ์ˆ˜๋ฅผ ์ง์ ‘ ์ง€์ •ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์ง์ ‘ ์ œ๊ณตํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. CPU ์ฝ”์–ด์˜ ํ• ๋‹น๊ณผ ์Šค์ผ€์ค„๋ง์€ ์šด์˜ ์ฒด์ œ์˜ ์ž‘์—…์ด๋ฉฐ, multiprocessing ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ์ด๋Ÿฌํ•œ ๋‚ฎ์€ ์ˆ˜์ค€์˜ ์ž์› ๊ด€๋ฆฌ์— ์ง์ ‘ ๊ฐœ์ž…ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜, ์ „์ฒด CPU ์ฝ”์–ด๋ฅผ ์ตœ๋Œ€ํ•œ ํ™œ์šฉํ•˜๋ ค๋Š” ๋ชฉ์ ์ด๋ผ๋ฉด, ์ž‘์—…์„ ๋” ๋งŽ์€ ํ”„๋กœ์„ธ์Šค์— ๋ถ„๋ฐฐํ•˜๊ฑฐ๋‚˜ ์‹œ์Šคํ…œ์˜ ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ ๋Šฅ๋ ฅ์„ ์ตœ๋Œ€๋กœ ํ™œ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๊ณ ๋ คํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ใ…ค ์ „์ฒด CPU ์ฝ”์–ด ์‚ฌ์šฉํ•˜๊ธฐ : ์‹œ์Šคํ…œ์— ์žˆ๋Š” ๋ชจ๋“  CPU ์ฝ”์–ด๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด, multiprocessing.cpu\_count() ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์‹œ์Šคํ…œ์— ์žˆ๋Š” ์ฝ”์–ด์˜ ์ˆ˜๋ฅผ ํ™•์ธํ•˜๊ณ , ์ด๋ฅผ Pool์˜ ์ธ์ž๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๋ฐฉ๋ฒ•์€ ์‹œ์Šคํ…œ์˜ ๋ชจ๋“  CPU ์ฝ”์–ด๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ๋ฅผ ์ˆ˜ํ–‰ํ•˜๋ ค๋Š” ๊ฒฝ์šฐ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค. ์•„๋ž˜ ์˜ˆ์‹œ๋ฅผ ์ฐธ๊ณ ํ•ด์ฃผ์„ธ์š” ๐Ÿค—

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# ์ „์ฒด CPU ์ฝ”์–ด ์‚ฌ์šฉํ•˜๊ธฐ
from multiprocessing import Pool, cpu_count

def my_task(data_chunk):
    # ๋ณต์žกํ•œ ๊ณ„์‚ฐ ์ˆ˜ํ–‰
    result = sum(data_chunk)
    return result

if __name__ == "__main__":
    data = range(1000000)  # ๋Œ€๋Ÿ‰์˜ ๋ฐ์ดํ„ฐ
    num_cores = cpu_count()  # ์‹œ์Šคํ…œ์˜ CPU ์ฝ”์–ด ์ˆ˜ ํ™•์ธ
    chunks = [data[i::num_cores] for i in range(num_cores)]  # ๋ฐ์ดํ„ฐ๋ฅผ CPU ์ฝ”์–ด ์ˆ˜๋งŒํผ ์ฒญํฌ๋กœ ๋‚˜๋ˆ”

    with Pool(num_cores) as p:  # ์‹œ์Šคํ…œ์˜ ๋ชจ๋“  CPU ์ฝ”์–ด ์‚ฌ์šฉ
        results = p.map(my_task, chunks)

๋ฉ€ํ‹ฐ์Šค๋ ˆ๋”ฉ ์ž์› ํ• ๋‹น ์˜ˆ์‹œ

์ด ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋”ฉ ์˜ˆ์‹œ์—์„œ๋Š” ์ „์ฒด ์ž‘์—… ๋ฒ”์œ„๋ฅผ 4๊ฐœ๋กœ ๋‚˜๋ˆ„์–ด ๊ฐ ์Šค๋ ˆ๋“œ๊ฐ€ ์ฒ˜๋ฆฌํ•˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๋ฐฉ์‹์€ ๊ฐ ์Šค๋ ˆ๋“œ๊ฐ€ ์ฒ˜๋ฆฌํ•  ๋ฐ์ดํ„ฐ์˜ ์–‘์„ ๋ช…ํ™•ํ•˜๊ฒŒ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ์ž‘์—…์˜ ๋ถ„๋ฐฐ๊ฐ€ ๊ณ ๋ฅด๊ฒŒ ์ด๋ฃจ์–ด์ง€๋„๋ก ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import threading

def my_task(start, end):
    # ๋ฒ”์œ„ ๋‚ด์˜ ์ˆซ์ž ํ•ฉ๊ณ„ ๊ณ„์‚ฐ
    result = sum(range(start, end))
    print(f"Result: {result}")

threads = []
for i in range(4):
    # ์ „์ฒด ๋ฒ”์œ„๋ฅผ 4๊ฐœ์˜ ๋ถ€๋ถ„์œผ๋กœ ๋‚˜๋ˆ„์–ด ๊ฐ ์Šค๋ ˆ๋“œ์— ํ• ๋‹น
    t = threading.Thread(target=my_task, args=(250000*i, 250000*(i+1)))
    threads.append(t)
    t.start()

for t in threads:
    t.join()

์ œ์‹œ๋œ ์˜ˆ์‹œ ์ฝ”๋“œ์—์„œ๋Š” ๊ฐ ์Šค๋ ˆ๋“œ๊ฐ€ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐ์ดํ„ฐ์˜ ์–‘์„ ๊ท ๋“ฑํ•˜๊ฒŒ ๋ถ„๋ฐฐํ•˜์˜€์Šต๋‹ˆ๋‹ค. ์ด๋Š” ๊ฐ ์ž‘์—… ๋‹จ์œ„๊ฐ€ ๋™์ผํ•œ ์ž์›์„ ์†Œ๋น„ํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ–ˆ์„ ๋•Œ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์‹ค์ œ๋กœ๋Š” ์ž‘์—…์˜ ๋ณต์žก๋„๊ฐ€ ๋‹ค๋ฅผ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ, ์œ„์—์„œ ์–ธ๊ธ‰ํ•œ ๋ฐฉ๋ฒ•๋“ค์„ ํ†ตํ•ด ์ž‘์—… ๋ถ„๋ฐฐ ๋ฐฉ์‹์„ ๋ณด๋‹ค ์„ธ๋ฐ€ํ•˜๊ฒŒ ์กฐ์ •ํ•  ํ•„์š”๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

์ž‘์—…์˜ ๋ณต์žก๋„๋‚˜ ์ž์› ์†Œ๋น„๋Ÿ‰์„ ๊ณ ๋ คํ•˜์—ฌ ์ž‘์—…์„ ํ• ๋‹นํ•˜๋Š” ๊ฒƒ์€ ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋”ฉ ํ”„๋กœ๊ทธ๋žจ์˜ ์„ฑ๋Šฅ์„ ์ตœ์ ํ™”ํ•˜๋Š” ๋ฐ ์ค‘์š”ํ•œ ์š”์†Œ์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ, ์ž‘์—…์˜ ํŠน์„ฑ์„ ์ •ํ™•ํžˆ ํŒŒ์•…ํ•˜๊ณ , ์ด์— ๊ธฐ๋ฐ˜ํ•œ ์ ์ ˆํ•œ ์ž‘์—… ๋ถ„๋ฐฐ ์ „๋žต์„ ์„ ํƒํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.

(์ฐธ๊ณ ) ๊ทธ๋ ‡๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋”ฉ ํ”„๋กœ๊ทธ๋žจ์˜ ์„ฑ๋Šฅ์„ ์ตœ์ ํ™”๋ฅผ ํ• ๊นŒ?

queue๋ฅผ ์‚ฌ์šฉํ•ด์„œ task์˜ ๋ณต์žก๋„๋ฅผ ์ •์˜ํ•˜๊ณ  ์ด๋ฅผ args๋กœ ๋„ฃ์–ด์ฃผ๋ฉด ๊ฐ ์Šค๋ ˆ๋“œ๊ฐ€ ์ฒ˜๋ฆฌํ•  ๋ฐ์ดํ„ฐ์˜ ์–‘์„ ๋ช…ํ™•ํ•˜๊ฒŒ ์ •์˜ํ•ด์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. (์•„๋ž˜ ์˜ˆ์‹œ์ฝ”๋“œ ์ฐธ๊ณ )

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import time
import queue

# ์ž‘์—… ํ•จ์ˆ˜
def worker(work_queue):
    while not work_queue.empty():
        try:
            # ํ์—์„œ ์ž‘์—…์„ ๊ฐ€์ ธ์˜ด
            task = work_queue.get_nowait()
        except queue.Empty:
            break

        # ์ž‘์—…์˜ ๋‚ด์šฉ(์—ฌ๊ธฐ์„œ๋Š” ๋‹จ์ˆœํžˆ ์ผ์ • ์‹œ๊ฐ„ ๋Œ€๊ธฐํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๊ฐ€์ •)
        print(f"{threading.current_thread().name} is processing task: {task}")
        time.sleep(task)
        print(f"{threading.current_thread().name} finished task: {task}")

        # ์ž‘์—… ์™„๋ฃŒ๋ฅผ ํ์— ์•Œ๋ฆผ
        work_queue.task_done()

# ์ž‘์—… ํ ์ƒ์„ฑ ๋ฐ ์ž‘์—… ์ถ”๊ฐ€
work_queue = queue.Queue()
tasks = [2, 4, 6, 8, 1, 3, 5, 7]  # ๊ฐ ์ˆซ์ž๋Š” ์ž‘์—…์˜ "๋ณต์žก๋„"๋ฅผ ๋‚˜ํƒ€๋ƒ„(์˜ˆ: ์ฒ˜๋ฆฌ ์‹œ๊ฐ„)
for task in tasks:
    work_queue.put(task)

# ์Šค๋ ˆ๋“œ ์ƒ์„ฑ ๋ฐ ์‹œ์ž‘
num_threads = 4
threads = []
for i in range(num_threads):
    t = threading.Thread(target=worker, args=(work_queue,))
    t.start()
    threads.append(t)

# ๋ชจ๋“  ์Šค๋ ˆ๋“œ์˜ ์ž‘์—…์ด ์™„๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ๋Œ€๊ธฐ
for t in threads:
    t.join()

print("All tasks are completed.")


-->