[python] ๋ฉํฐํ๋ก์ธ์ฑ Pool ์ฌ์ฉ๋ฒ ๋ฐ ์ฝ๋ ์์ | multiprocessing.Pool | python ์๋ ํฅ์
๋ฉํฐํ๋ก์ธ์ฑ์ ์ฌ๋ฌ ๊ฐ์ ๋ ๋ฆฝ์ ์ธ ํ๋ก์ธ์ค๋ฅผ ์์ฑํ์ฌ ๊ฐ๊ฐ์ ํ๋ก์ธ์ค๊ฐ ๋ณ๋ ฌ๋ก ์์ ํ๋๋ก ํ๋ ๋ฐฉ์์ด๋ค. ๊ฐ ํ๋ก์ธ์ค๋ ๋ ๋ฆฝ์ ์ธ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ์ ๊ฐ์ง๋ฉฐ, ํ๋ก์ธ์ค ๊ฐ ํต์ (Inter-Process Co
mvje.tistory.com
ํ์ด์ฌ์์ ๋ฉํฐํ๋ก์ธ์ฑ์ ๊ตฌํํ๊ธฐ ์ํด multiprocessing ๋ชจ๋์ ์ฌ์ฉํ ์ ์์ผ๋ฉฐ, ์ด ์ค ๋ํ์ ์ธ ๋ฐฉ์์ผ๋ก multiprocessing.Pool๊ณผ multiprocessing.Process๊ฐ ์๋ค. ์ด์ ํฌ์คํ ์์๋ Pool์ ์ค์ฌ์ผ๋ก ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ์ดํด๋ณด์๊ณ , ์ด๋ฒ์๋ Process๋ฅผ ์ง์ ์ฌ์ฉํ๋ ๋ฐฉ์๊ณผ ํจ๊ป ๋ ๋ฐฉ์์ ์ฐจ์ด์ ์ ๋น๊ตํด๋ณด๋ ค ํ๋ค.
Pool๊ณผ Process๋ ๋ฉํฐํ๋ก์ธ์ฑ์ ๊ตฌํํ๋ ๋ ๊ฐ์ง ์ ๊ทผ ๋ฐฉ์์ผ๋ก, ์ํฉ์ ๋ฐ๋ผ ๋ ์ ํฉํ ๋ฐฉ์์ด ๋ฌ๋ผ์ง ์ ์๋ค. ํนํ ๊ฐ ํ๋ก์ธ์ค์ ์๋ก ๋ค๋ฅธ ์์ ์ ํ ๋นํด์ผ ํ๋ ๊ฒฝ์ฐ์๋ Process๋ฅผ ์ง์ ์ฌ์ฉํ๋ ๊ฒ์ด ์ ๋ฆฌํ๋ค.
๐ multiprocessing.Pool
โ
๊ฐํธํ ์ธํฐํ์ด์ค
Pool ํด๋์ค๋ ์ฌ๋ฌ ๊ฐ์ ํ๋ก์ธ์ค๋ฅผ ์์ฑํ๊ณ , ๊ฐ ํ๋ก์ธ์ค์ ์์
์ ๋ถ๋ฐฐํ๋ ๊ณผ์ ์ ๊ฐ๋จํ๊ฒ ๋ง๋ค์ด์ค๋ค. ๋์ผํ ํจ์๋ฅผ ์ฌ๋ฌ ์
๋ ฅ๊ฐ์ ๋ณ๋ ฌ๋ก ์ ์ฉํ ๋ ํนํ ํธ๋ฆฌํ๋ค.
โ
์์
๋ถ๋ฐฐ ์๋ํ
map, imap, apply ๋ฑ์ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ฉด ์
๋ ฅ ๋ฐ์ดํฐ๋ฅผ ์๋์ผ๋ก ๋๋ ์ฌ๋ฌ ํ๋ก์ธ์ค์ ๋ถ์ฐ์ํค๊ณ , ๊ฒฐ๊ณผ๋ฅผ ๋ณํฉํ๋ ์์
๊น์ง ๋ด๋ถ์ ์ผ๋ก ์ฒ๋ฆฌ๋๋ค.
โ
ํ๋ก์ธ์ค ์ ์ ์ด
Pool(processes=n) ํํ๋ก ์์ฑ ์ ์ฌ์ฉํ ํ๋ก์ธ์ค์ ๊ฐ์๋ฅผ ์ง์ ํ ์ ์๋ค. ์ด๋ CPU ์ฝ์ด ์ ๋๋ ๋ณ๋ ฌ์ฒ๋ฆฌํ ์์
์์ ๋ฐ๋ผ ์กฐ์ ํ ์ ์๋ค.
# ์ฝ๋ ์์
from multiprocessing import Pool
def square_number(x):
return x ** 2
if __name__ == "__main__":
data = [1, 2, 3, 4, 5]
with Pool(processes=3) as pool:
results = pool.map(square_number, data)
print("Results:", results)
๐ multiprocessing.Process
โ
์ธ๋ฐํ ์ ์ด๊ฐ ํ์ํ ๊ฒฝ์ฐ์ ์ ํฉ
Process ํด๋์ค๋ฅผ ์ฌ์ฉํ๋ฉด ๊ฐ ํ๋ก์ธ์ค๋ฅผ ๋ช
์์ ์ผ๋ก ์์ฑํ๊ณ , ์์(start()), ์ข
๋ฃ(terminate()), ๋๊ธฐ(join()) ๋ฑ์ ๋์์ ์ธ๋ฐํ๊ฒ ์ ์ดํ ์ ์๋ค. ์์
ํ๋ฆ์ ์ง์ ๊ด๋ฆฌํด์ผ ํ์ง๋ง, ๊ทธ๋งํผ ์ ์ฐํ๊ฒ ์ค๊ณํ ์ ์๋ค๋ ์ฅ์ ์ด ์๋ค.
โ
ํ๋ก์ธ์ค ๊ฐ ํต์ (IPC) ๊ตฌํ ํ์
Process ๋ฐฉ์์์๋ ํ๋ก์ธ์ค ๊ฐ ๋ฐ์ดํฐ ๊ณต์ ๋ฅผ ์ง์ ์ฒ๋ฆฌํด์ฃผ์ด์ผ ํ๋ค. ์ด๋ฅผ ์ํด Queue, Pipe, Value, Array ๋ฑ์ IPC(Inter-Process Communication) ๋ฉ์ปค๋์ฆ์ ์ฌ์ฉํ๋ค. ๊ทธ๋งํผ ๊ตฌํ ๋์ด๋๋ ์ฝ๊ฐ ๋์ง๋ง, ๋ณต์กํ ๋ฐ์ดํฐ ํ๋ฆ์ ์ฒ๋ฆฌํ ์ ์๋ค.
โ
๋ค์ํ ์์
์ฒ๋ฆฌ์ ์ ๋ฆฌ
Pool์ด ๋์ผํ ํจ์๋ฅผ ์ฌ๋ฌ ๋ฐ์ดํฐ์ ์ ์ฉํ ๋ ์ ์ฉํ ๋ฐ๋ฉด, Process๋ ์๋ก ๋ค๋ฅธ ์์
์ ๋ณ๋ ฌ๋ก ์ํํด์ผ ํ๋ ๊ฒฝ์ฐ์ ์ ํฉํ๋ค. ์๋ฅผ ๋ค์ด, ํ๋๋ ์๋ฒ๋ฅผ ์คํํ๊ณ ๋ค๋ฅธ ํ๋๋ ๋ฐ์ดํฐ ๋ก๊น
์ ์ํํ๋ ์์ ๋ณ๋ ฌ ์์
์ฒ๋ฆฌ์ ์์ฃผ ์ฐ์ธ๋ค.
# ์ฝ๋ ์์ - ๊ธฐ๋ณธ
from multiprocessing import Process, Queue
def square_numbers(numbers, result_queue):
squared_numbers = [x ** 2 for x in numbers]
result_queue.put(squared_numbers)
if __name__ == "__main__":
data = [1, 2, 3, 4, 5]
result_queue = Queue()
# ๊ฐ ํ๋ก์ธ์ค๊ฐ ๋
๋ฆฝ์ ์ผ๋ก ์คํ๋๋ฉฐ, ์๋ก ๋ค๋ฅธ ์์
์ ์ํ
num_of_processes = 3
processes = [Process(target=square_numbers, args=(data, result_queue)) for _ in range(num_of_processes)]
for process in processes:
process.start()
for process in processes:
process.join()
# ๊ฒฐ๊ณผ๋ฅผ ํ์์ ์์ง
results = [result_queue.get() for _ in processes]
print("Results:", results)
- ์ด ์์์์๋ square_numbers ํจ์๊ฐ ๊ฐ๊ฐ์ ํ๋ก์ธ์ค์์ ์คํ๋จ
- ๊ฐ ํ๋ก์ธ์ค๋ ๋ ๋ฆฝ์ ์ผ๋ก data ๋ฆฌ์คํธ์ ์ซ์๋ฅผ ์ ๊ณฑํ๊ณ , ๊ทธ ๊ฒฐ๊ณผ๋ฅผ result_queue์ ๋ฃ์
- ๋ฉ์ธ ํ๋ก์ธ์ค์์๋ ๊ฐ ํ๋ก์ธ์ค์ ๊ฒฐ๊ณผ๋ฅผ ์์งํ์ฌ ์ถ๋ ฅ
# ์ฝ๋ ์์ - ๊ฐ ํ๋ก์ธ์ค์์ ์๋ก ๋ค๋ฅธ ์์ ์ ์ํ
from multiprocessing import Process, Queue
def square_numbers(numbers, result_queue):
squared_numbers = [x ** 2 for x in numbers]
result_queue.put(squared_numbers)
def cube_numbers(numbers, result_queue):
cubed_numbers = [x ** 3 for x in numbers]
result_queue.put(cubed_numbers)
if __name__ == "__main__":
data = [1, 2, 3, 4, 5]
result_queue = Queue()
# ๊ฐ ํ๋ก์ธ์ค์ ๋ค๋ฅธ ํจ์ ํ ๋น
process1 = Process(target=square_numbers, args=(data, result_queue))
process2 = Process(target=cube_numbers, args=(data, result_queue))
# ํ๋ก์ธ์ค ์์
process1.start()
process2.start()
# ํ๋ก์ธ์ค ์ข
๋ฃ ๋๊ธฐ
process1.join()
process2.join()
# ๊ฒฐ๊ณผ๋ฅผ ํ์์ ์์ง
results = [result_queue.get(), result_queue.get()]
print("Squared Results:", results[0])
print("Cubed Results:", results[1])
- ํ๋ก์ธ์ค๋ฅผ ์ฌ๋ฌ๊ฐ ๋ง๋ค๊ณ ๊ฐ ํ๋ก์ธ์ค๋ง๋ค ์๋ก ๋ค๋ฅธ ํจ์๋ฅผ target์ผ๋ก ๋ฃ์ด์ฃผ๋ฉด ๊ฐ ํ๋ก์ธ์ค์์ ์๋ก ๋ค๋ฅธ ํจ์๋ฅผ ์คํํ ์ ์๋ค.
- ์์์์๋ ์ซ์๋ฅผ ์ ๊ณฑํ๋ square_numbers ํจ์์ ์ซ์๋ฅผ ์ธ์ ๊ณฑํ๋ cube_numbers ํจ์๋ฅผ ์๋ก ๋ค๋ฅธ ํ๋ก์ธ์ค๋ก ์คํ