Pool

ํ˜œ์ฟฐยท2023๋…„ 10์›” 18์ผ
0
post-thumbnail

๐Ÿ“ข python์—์„œ์˜ ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋”ฉ

ํŒŒ์ด์ฌ์—์„œ ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋”ฉ์„ ์‚ฌ์šฉํ•  ์ˆ˜๋Š” ์žˆ์ง€๋งŒ, ํŠน์ • ๊ฒฝ์šฐ์—๋Š” ์ œ์•ฝ์‚ฌํ•ญ์ด ์žˆ๋‹ค.

1. Global Interpreter Lock (GIL):

  • ํŒŒ์ด์ฌ์˜ CPython ๊ตฌํ˜„์—๋Š” GIL์ด๋ผ๊ณ  ํ•˜๋Š” Global Interpreter Lock์ด ์žˆ๋‹ค. ์ด๊ฒƒ์€ ํ•œ ๋ฒˆ์— ํ•˜๋‚˜์˜ ์Šค๋ ˆ๋“œ๋งŒ ํŒŒ์ด์ฌ ๋ฐ”์ดํŠธ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋„๋ก ํ•˜๋Š” ๋ฎคํ…์Šค(๋ฝ)์ด๋‹ค.
  • GIL์€ ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ํ™˜๊ฒฝ์—์„œ ์—ฌ๋Ÿฌ CPU ์ฝ”์–ด๋ฅผ ํ™œ์šฉํ•˜๋Š” ๋ฐ ์ œํ•œ์„ ๊ฐ€ํ•œ๋‹ค. ๋”ฐ๋ผ์„œ CPU-bound ์ž‘์—…(๊ณ„์‚ฐ ์ง‘์•ฝ์ ์ธ ์ž‘์—…)์„ ๋ณ‘๋ ฌ๋กœ ์ฒ˜๋ฆฌํ•  ๋•Œ ์ด์ ์„ ์ œ๊ณตํ•˜์ง€ ์•Š๋Š”๋‹ค.

2. I/O-bound ์ž‘์—…์€ ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋”ฉ์„ ํ†ตํ•ด ๊ฐœ์„  ๊ฐ€๋Šฅ:

  • I/O-bound ์ž‘์—…(์˜ˆ: ํŒŒ์ผ ์ฝ๊ธฐ/์“ฐ๊ธฐ, ๋„คํŠธ์›Œํฌ ํ†ต์‹ , ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ฟผ๋ฆฌ)์€ ๋Œ€๊ธฐ ์‹œ๊ฐ„์ด ๋ฐœ์ƒํ•˜๋ฏ€๋กœ ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋”ฉ์„ ์‚ฌ์šฉํ•˜์—ฌ ์—ฌ๋Ÿฌ ์ž‘์—…์„ ๋ณ‘๋ ฌ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค. GIL์€ I/O-bound ์ž‘์—…์— ๋Œ€ํ•œ ๋ณ‘๋ ฌํ™”๋ฅผ ์ œํ•œํ•˜์ง€ ์•Š๋Š”๋‹ค.

3. CPU-bound ์ž‘์—…์˜ ๊ฒฝ์šฐ ๋ฉ€ํ‹ฐํ”„๋กœ์„ธ์‹ฑ์„ ๊ณ ๋ ค:

  • CPU-bound ์ž‘์—…์„ ๋ณ‘๋ ฌ๋กœ ์ฒ˜๋ฆฌํ•˜๋ ค๋ฉด ๋ฉ€ํ‹ฐํ”„๋กœ์„ธ์‹ฑ์„ ๊ณ ๋ คํ•ด์•ผ ํ•œ๋‹ค. ๋ฉ€ํ‹ฐํ”„๋กœ์„ธ์‹ฑ์€ ๊ฐ ํ”„๋กœ์„ธ์Šค๊ฐ€ ๋ณ„๋„์˜ ์ธํ„ฐํ”„๋ฆฌํ„ฐ ์ธ์Šคํ„ด์Šค๋ฅผ ๊ฐ€์ง€๊ธฐ ๋•Œ๋ฌธ์— GIL์˜ ์˜ํ–ฅ์„ ๋ฐ›์ง€ ์•Š๋Š”๋‹ค. ๋”ฐ๋ผ์„œ CPU-bound ์ž‘์—…์˜ ๋ณ‘๋ ฌํ™”์—๋Š” ๋ฉ€ํ‹ฐํ”„๋กœ์„ธ์‹ฑ์ด ๋” ์ ํ•ฉํ•˜๋‹ค.

4. ์Šค๋ ˆ๋“œ ๊ฐ„ ๋™๊ธฐํ™” ๋ฌธ์ œ:

  • ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋”ฉ์„ ์‚ฌ์šฉํ•  ๋•Œ ์Šค๋ ˆ๋“œ ๊ฐ„์— ๋ฐ์ดํ„ฐ ๊ณต์œ  ๋ฐ ๋™๊ธฐํ™” ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•ด์•ผ ํ•œ๋‹ค. ์ด๋Š” ๋ณต์žก์„ฑ์„ ์ฆ๊ฐ€์‹œํ‚ค๊ณ  ๋ฒ„๊ทธ์˜ ๊ฐ€๋Šฅ์„ฑ์„ ๋†’์ธ๋‹ค.

์š”์•ฝํ•˜๋ฉด, ํŒŒ์ด์ฌ์˜ GIL์€ ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋”ฉ์„ ํ†ตํ•œ ๋ณ‘๋ ฌํ™”๋ฅผ ์ œํ•œํ•˜๋ฉฐ, CPU-bound ์ž‘์—…์„ ๋ณ‘๋ ฌ๋กœ ์ฒ˜๋ฆฌํ•˜๋ ค๋ฉด ๋ฉ€ํ‹ฐํ”„๋กœ์„ธ์‹ฑ์ด ๋” ์ ํ•ฉํ•˜๋‹ค. ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋”ฉ์€ ์ฃผ๋กœ I/O-bound ์ž‘์—… ๋ฐ ๋™์‹œ์„ฑ์„ ๋‹ค๋ฃฐ ๋•Œ ์œ ์šฉํ•˜๋‹ค.

๐Ÿ“ข Pool

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

๐Ÿ”Ž Pool์˜ ์ฃผ์š” ๊ฐœ๋…๊ณผ ์‚ฌ์šฉ๋ฒ•

1. ํ’€ ์ƒ์„ฑ

Pool ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•  ๋•Œ, ๋ณ‘๋ ฌ๋กœ ์‹คํ–‰ํ•˜๋ ค๋Š” ํ”„๋กœ์„ธ์Šค ์ˆ˜๋ฅผ ์ง€์ •ํ•œ๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ CPU ์ฝ”์–ด ์ˆ˜๋‚˜ ์›ํ•˜๋Š” ๋ณ‘๋ ฌ์„ฑ ์ˆ˜์ค€์— ๋”ฐ๋ผ ํ”„๋กœ์„ธ์Šค ์ˆ˜๋ฅผ ์„ ํƒํ•˜๋ฉด ๋œ๋‹ค.

from multiprocessing import Pool

# ์›ํ•˜๋Š” ๋ณ‘๋ ฌ์„ฑ ์ˆ˜์ค€์„ ์„ค์ •
pool = Pool(processes=4)  # 4๊ฐœ์˜ ํ”„๋กœ์„ธ์Šค๋กœ ์ž‘์—…์„ ๋ณ‘๋ ฌ๋กœ ์‹คํ–‰

2. ์ž‘์—… ๋ถ„๋ฐฐ

Pool์€ ์ž‘์—…์„ ๋ณ‘๋ ฌ ํ”„๋กœ์„ธ์Šค๋กœ ๋ถ„๋ฐฐํ•˜๊ณ  ๊ฐ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•œ๋‹ค. pool.map() ๋˜๋Š” pool.apply_async()๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ž‘์—…์„ ํ’€์— ์ถ”๊ฐ€ํ•œ๋‹ค.

  • pool.map(function, iterable): ๋ฐ˜๋ณต ๊ฐ€๋Šฅํ•œ ๊ฐ์ฒด ๋‚ด์˜ ์š”์†Œ๋ฅผ ํ•จ์ˆ˜์— ๋งคํ•‘ํ•˜๊ณ  ๊ฒฐ๊ณผ๋ฅผ ์ˆœ์ฐจ์ ์œผ๋กœ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
  • pool.apply_async(function, args): ํ•จ์ˆ˜๋ฅผ ๋น„๋™๊ธฐ์ ์œผ๋กœ ํ˜ธ์ถœํ•˜๊ณ  AsyncResult ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

3. ์ž‘์—… ์‹คํ–‰

Pool์€ ์ƒ์„ฑ๋œ ํ”„๋กœ์„ธ์Šค ํ’€์—์„œ ์ž‘์—…์„ ๋ณ‘๋ ฌ๋กœ ์‹คํ–‰ํ•œ๋‹ค. ์ž‘์—…์ด ์™„๋ฃŒ๋˜๋ฉด ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ฑฐ๋‚˜ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

results = pool.map(some_function, some_iterable)

4. ๊ฒฐ๊ณผ ์ฒ˜๋ฆฌ

๊ฐ ์ž‘์—…์ด ์™„๋ฃŒ๋˜๋ฉด ๊ฒฐ๊ณผ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ฑฐ๋‚˜, ํ•„์š”์— ๋”ฐ๋ผ ์ €์žฅํ•  ์ˆ˜ ์žˆ๋‹ค.

for result in results:
    process(result)

5. ํ’€ ์ข…๋ฃŒ

์ž‘์—…์ด ์™„๋ฃŒ๋˜๋ฉด pool.close()๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ํ’€์„ ๋‹ซ๊ณ , pool.join()์„ ํ˜ธ์ถœํ•˜์—ฌ ๋ชจ๋“  ์ž‘์—…์ด ์™„๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ๋Œ€๊ธฐํ•œ๋‹ค.

pool.close()
pool.join()

Pool์„ ์‚ฌ์šฉํ•˜๋ฉด CPU ๋ฐ”์šด๋“œ ์ž‘์—…์„ ํšจ๊ณผ์ ์œผ๋กœ ๋ณ‘๋ ฌ๋กœ ์‹คํ–‰ํ•˜๊ณ , ๋ฉ€ํ‹ฐ์ฝ”์–ด ํ”„๋กœ์„ธ์„œ์—์„œ ๋†’์€ ์„ฑ๋Šฅ์„ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค.

0๊ฐœ์˜ ๋Œ“๊ธ€