TIL-080 | Python_ GIL(Global Interpreter Lock)

Lee, Chankyuยท2022๋…„ 2์›” 3์ผ
0
post-thumbnail

๐ŸŒˆ GIL(Global Interpreter Lock)

GIL์ด๋ž€?

  • GIL์ด๋ž€ ํŒŒ์ด์ฌ ์ธํ„ฐํ”„๋ฆฌํ„ฐ๊ฐ€ ํ•œ ์Šค๋ ˆ๋“œ๋งŒ ํ•˜๋‚˜์˜ ๋ฐ”์ดํŠธ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ฃผ๋Š” Lock์ด๋‹ค.
    ๋‹ค์‹œ ๋งํ•ด, ํ•œ ์Šค๋ ˆ๋“œ๋งŒ์ด ํŒŒ์ด์ฌ ์ธํ„ฐํ”„๋ฆฌํ„ฐ๋ฅผ ์ปจํŠธ๋กคํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค€๋‹ค.

  • ํ•˜๋‚˜์˜ ์Šค๋ ˆ๋“œ์— ๋ชจ๋“  ์ž์›์„ ํ—ˆ๋ฝํ•˜๊ณ  ๊ทธ ํ›„์—๋Š” Lock์„ ๊ฑธ์–ด ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ๋Š” ์‹คํ–‰ํ•  ์ˆ˜ ์—†๊ฒŒ ๋ง‰๋Š”๋‹ค.

  • ๋”ฐ๋ผ์„œ ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ๋ฅผ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ thread context switch์— ๋”ฐ๋ฅธ ๋น„์šฉ๋„ ๋ฐœ์ƒํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์‹ฑ๊ธ€์Šค๋ ˆ๋“œ์ผ๋•Œ๋ณด๋‹ค ์˜คํžˆ๋ ค ์‹œ๊ฐ„์ด ์˜ค๋ž˜ ๊ฑธ๋ฆฌ๋Š” ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธด๋‹ค.

GIL์„ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ ๋Š”?

  • ํŒŒ์ด์ฌ์€ GC(Garbage collection)๋ฅผ ์œ„ํ•ด reference counting์„ ํ†ตํ•ด ํ• ๋‹น๋œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๊ด€๋ฆฌํ•œ๋‹ค. ํŒŒ์ด์ฌ ์˜ค๋ธŒ์ ํŠธ๋งˆ๋‹ค ๋ ˆํผ๋Ÿฐ์Šค๋กœ ์‚ฌ์šฉ๋œ ํšŸ์ˆ˜๋ฅผ ์ €์žฅํ•˜๊ณ , 0์ด ๋˜๋Š” ๊ฒฝ์šฐ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ํ•ด์ œํ•œ๋‹ค. ์ด๊ฒƒ์€ GIL์‚ฌ์šฉ ์ด์œ ์™€ ๋ฐ€์ ‘ํ•œ ์—ฐ๊ด€์ด ์žˆ๋‹ค.
    (๐Ÿ‘‰ Garbage Collection ๊ด€๋ จํ•ด์„œ๋Š” ์ถ”ํ›„ ๊ธ€์„ ์ž‘์„ฑํ•˜๋„๋ก ํ•˜๊ฒ ๋‹ค.)

  • ์ฐธ์กฐ ํšŸ์ˆ˜์— ๊ธฐ๋ฐ˜ํ•˜์—ฌ GC๋ฅผ ์ง„ํ–‰ํ•˜๋Š” Python์˜ ํŠน์„ฑ์ƒ, ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์“ฐ๋ ˆ๋“œ๊ฐ€ Python ์ธํ„ฐํ”„๋ฆฌํ„ฐ๋ฅผ ๋™์‹œ์— ์‹คํ–‰ํ•˜๋ฉด Race Condition์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
    Race Condition์ด๋ž€, ํ•˜๋‚˜์˜ ๊ฐ’์— ์—ฌ๋Ÿฌ ์“ฐ๋ ˆ๋“œ๊ฐ€ ๋™์‹œ์— ์ ‘๊ทผํ•จ์œผ๋กœ์จ ๊ฐ’์ด ์˜ฌ๋ฐ”๋ฅด์ง€ ์•Š๊ฒŒ ์ฝํžˆ๊ฑฐ๋‚˜ ์“ฐ์ผ ์ˆ˜ ์žˆ๋Š” ์ƒํƒœ๋ฅผ ๋งํ•œ๋‹ค. ์ด๋Ÿฌํ•œ ์ƒํ™ฉ์„ ๋ณด๊ณ  Thread-safe ํ•˜์ง€ ์•Š๋‹ค๊ณ  ํ‘œํ˜„ํ•˜๊ธฐ๋„ ํ•œ๋‹ค.

  • ์—ฌ๋Ÿฌ ์“ฐ๋ ˆ๋“œ๊ฐ€ Python ์ธํ„ฐํ”„๋ฆฌํ„ฐ๋ฅผ ๋™์‹œ์— ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋‘๋ฉด ๊ฐ ๊ฐ์ฒด์˜ ์ฐธ์กฐ ํšŸ์ˆ˜๊ฐ€ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๊ด€๋ฆฌ๋˜์ง€ ๋ชปํ•  ์ˆ˜๋„ ์žˆ๊ณ , ์ด๋กœ ์ธํ•ด GC๊ฐ€ ์ œ๋Œ€๋กœ ๋™์ž‘ํ•˜์ง€ ์•Š์„ ์ˆ˜๋„ ์žˆ๋‹ค. ์ด๋Ÿฌํ•œ Race Condition์€ ๋ฎคํ…์Šค(Mutex)๋ฅผ ์ด์šฉํ•˜๋ฉด ์˜ˆ๋ฐฉํ•  ์ˆ˜ ์žˆ๋‹ค.

  • ๋ฎคํ…์Šค(Mutex)๋ž€, ๋ฉ€ํ‹ฐ ์“ฐ๋ ˆ๋”ฉ ํ™˜๊ฒฝ์—์„œ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์“ฐ๋ ˆ๋“œ๊ฐ€ ์–ด๋– ํ•œ ๊ณต์œ  ์ž์›์— ์ ‘๊ทผ ๊ฐ€๋Šฅํ•  ๋•Œ ๊ทธ ๊ณต์œ  ์ž์›์— ์ ‘๊ทผํ•˜๊ธฐ ์œ„ํ•ด ๊ฐ€์ง€๊ณ  ์žˆ์–ด์•ผ ํ•˜๋Š” ์ผ์ข…์˜ key์™€ ๊ฐ™๋‹ค.
    ๋งŒ์•ฝ ํ•œ ์“ฐ๋ ˆ๋“œ๊ฐ€ ์–ด๋– ํ•œ ๊ณต์œ  ์ž์›์— ๋Œ€ํ•œ ๋ฎคํ…์Šค๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค๋ฉด, ๋‹ค๋ฅธ ์“ฐ๋ ˆ๋“œ๋“ค์€ ๊ทธ ๊ณต์œ  ์ž์›์— ์ ‘๊ทผํ•˜๊ณ  ์‹ถ์„ ๋•Œ๋„ ๊ทธ ๊ณต์œ  ์ž์›์— ์ ‘๊ทผํ•˜๊ณ  ์žˆ๋Š” ์“ฐ๋ ˆ๋“œ๊ฐ€ ๋ฎคํ…์Šค๋ฅผ ํ’€์–ด์ค„ ๋•Œ๊นŒ์ง€๋Š” ๊ธฐ๋‹ค๋ ค์•ผ ํ•œ๋‹ค.

  • ์ฆ‰, ํ•˜๋‚˜์˜ Lock์„ ํ†ตํ•ด์„œ ๋ชจ๋“  ๊ฐ์ฒด๋“ค์— ๋Œ€ํ•œ reference count์˜ ๋™๊ธฐํ™” ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜์˜€๋‹ค.
import sys

a = []
b = a
print(sys.getrefcount(a)) # 3
  • ๋นˆ ๋ฐฐ์—ด [] ๋Š” a, b, sys.getrefcount์— ์˜ํ•ด ์ฐธ์กฐ๋˜๊ณ  ์žˆ์–ด refcount๋Š” 3์ด๋‹ค.

Python์—์„œ์˜ ๋ฉ€ํ‹ฐ ์Šค๋ ˆ๋”ฉ์€ ํ•ญ์ƒ ์†ํ•ด์ธ๊ฐ€?

  • ์œ„์—์„œ ์–ธ๊ธ‰ํ•œ๋ฐ”์™€ ๊ฐ™์ด, CPU ์—ฐ์‚ฐ์˜ ๋น„์ค‘์ด ํฐ ์ž‘์—…์„ ํ•  ๋•Œ ๋ฉ€ํ‹ฐ ์“ฐ๋ ˆ๋”ฉ์€ ์˜คํžˆ๋ ค ์„ฑ๋Šฅ์„ ๋–จ์–ด๋œจ๋ฆฐ๋‹ค. ๋ณ‘๋ ฌ์ ์ธ ์‹คํ–‰์€ ๋ถˆ๊ฐ€๋Šฅํ•œ๋ฐ ๊ดœํžˆ ๋ฌธ๋งฅ ์ „ํ™˜(Context Switching) ๋น„์šฉ๋งŒ ์žก์•„๋จน๋Š”๋‹ค.

  • ๊ทธ๋Ÿฌ๋‚˜, CPU ์—ฐ์‚ฐ์˜ ๋น„์ค‘์ด ์ ์€, ์ฆ‰ ์™ธ๋ถ€ ์—ฐ์‚ฐ(I/O, Sleep ๋“ฑ)์˜ ๋น„์ค‘์ด ํฐ ์ž‘์—…์„ ํ•  ๋•Œ๋Š” ๋ฉ€ํ‹ฐ ์“ฐ๋ ˆ๋”ฉ์ด ๊ต‰์žฅํžˆ ์ข‹์€ ์„ฑ๋Šฅ์„ ๋ณด์ธ๋‹ค. ๋”ฐ๋ผ์„œ Python์—์„œ ๋ฉ€ํ‹ฐ ์“ฐ๋ ˆ๋”ฉ์ด ๋ฌด์กฐ๊ฑด ์•ˆ ์ข‹๋‹ค๋Š” ๋ง์€ ์‚ฌ์‹ค์ด ์•„๋‹ˆ๋‹ค. ์‹ค์ œ๋กœ, I/O ํ˜น์€ Sleep ๋“ฑ์˜ ์™ธ๋ถ€ ์—ฐ์‚ฐ์ด ๋Œ€๋ถ€๋ถ„์ด๋ผ๋ฉด ๋ฉ€ํ‹ฐ ์“ฐ๋ ˆ๋”ฉ์„ ํ†ตํ•ด ํฐ ์„ฑ๋Šฅ ํ–ฅ์ƒ์„ ๊ธฐ๋Œ€ํ•  ์ˆ˜ ์žˆ๋‹ค.
    ์•„๋ž˜์˜ ์˜ˆ์‹œ๋ฅผ ๋ณด๋ฉด ๋ฉ€ํ‹ฐ ์Šค๋ ˆ๋”ฉ์„ ํ†ตํ•ด ๋” ๋นจ๋ผ์ง„ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

import threading
import time

def sleep_for_2s():
    time.sleep(2)

#Single Thread
start = time.time()
sleep_for_2s()
sleep_for_2s()
end = time.time()
print('[Single Thread] total time : {}'.format(end - start))

# Multi Thread
start = time.time()
thread1 = threading.Thread(target=sleep_for_2s)
thread2 = threading.Thread(target=sleep_for_2s)
thread1.start()
thread2.start()
thread1.join()
thread2.join()
end = time.time()
print('[Multi Thread] total time : {}'.format(end - start))

[Single Thread] total time : 4.006161451339722
[Multi Thread] total time : 2.0036208629608154

๐Ÿ“ Reference

  1. https://torbjorn.tistory.com/669
  2. https://velog.io/@doondoony/Python-GIL
  3. https://ssungkang.tistory.com/entry/python-GIL-Global-interpreter-Lock%EC%9D%80-%EB%AC%B4%EC%97%87%EC%9D%BC%EA%B9%8C
  4. http://www.dabeaz.com/python/UnderstandingGIL.pdf
  5. https://it-eldorado.tistory.com/160
profile
Backend Developer - "Growth itself contains the germ of happiness"

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

๊ด€๋ จ ์ฑ„์šฉ ์ •๋ณด