ํ‹ฐ์Šคํ† ๋ฆฌ ๋ทฐ

โœจ multiprocessing์ด ํ•„์š”ํ•œ ์ด์œ 

๋งŽ์€ ๊ฐœ๋ฐœ์ž๋“ค์ด ํ•˜๋Š” ์ผ ์ค‘ ํ•˜๋‚˜๋Š” ๊ธฐ๋‹ค๋ฆฌ๊ธฐ์ผ ๊ฒƒ์ด๋‹ค. ์ตœ๊ทผ ํšŒ์‚ฌ์— ์ทจ์—…์„ ํ•˜๊ณ  ๋‚˜์„œ ์ œ์ผ ๋จผ์ € ๋งก์€ ์ผ์€ ๋‘๊ฐœ์˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์กด์žฌํ•˜๋Š” sequence ์ •๋ณด๋“ค์„ ๊ฐ€์ง€๊ณ  similarity๋ฅผ ๊ตฌํ•ด relation ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์ธ๋ฐ ๊ฑฐ์˜ ์ผ์ฃผ์ผ ๋„˜๊ฒŒ ์‚ฝ์งˆ์„ ํ•˜์˜€๋‹ค. (ํ˜ผ๋‚จ์˜ ์—ฐ์†..๐Ÿ™‡๐Ÿป‍โ™€๏ธ) ๊ฐ ๋ฐ์ดํ„ฐํ”„๋ ˆ์ž„์˜ sequence๋“ค์„ cross mappingํ•˜์—ฌ ๊ณ„์‚ฐํ•ด์•ผํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋Œ€๋žต์ ์œผ๋กœ ์ฝ”๋“œ๋ฅผ ์งœ๋ฉด ์•„๋ž˜์™€ ๊ฐ™๋‹ค(sequence similarity ๊ณ„์‚ฐ์€ ์ƒ๋žตํ•˜๊ณ  sequence๋ฅผ ๋‹จ์ˆœํžˆ ๋”ํ•˜๋Š” ๊ณ„์‚ฐ ์ฝ”๋“œ์ž„)

def calculate(first_df, second_df):
    results = []
    for first_index, first_seq in first_df.values:
        for second_index, second_seq in second_df.values:
            results.append(first_seq+second_seq)
            
    return results

๋ฐ์ดํ„ฐ๊ฐ€ ์ ์œผ๋ฉด ๋Œ๋ ค๋„ ์˜ค๋ž˜ ๊ฑธ๋ฆด ์ผ์ด ์—†์ง€๋งŒ ๋‚˜๊ฐ™์€ ๊ฒฝ์šฐ๋Š”..3000 row์˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€ 8000 row์˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ผ ๋Œ€๋žต ๊ณ„์‚ฐํ–ˆ์„ ๋•Œ ์•ฝ 14์‹œ๊ฐ„ ์‹ค์ œ๋กœ๋Š” ๋” ์˜ค๋ž˜ ๊ฑธ๋ฆด ๊ฒƒ์ด๋‹ค. ๊ฐœ๋ฐœ์ž์—๊ฒŒ ์ด๋Ÿฐ ๋น„ํšจ์œจ์ ์ธ ์ฝ”๋“œ๋Š” ํšจ์œจํ™”์˜ ์š•๊ตฌ๋ฅผ ๋ถˆ๋Ÿฌ์ผ์œผํ‚ฌ ๊ฒƒ์ด๋‹ค. ๊ทธ๋ž˜์„œ ์‚ฌ์šฉํ•œ๊ฒŒ multiprocessing module์ด๋‹ค.

 

โœจ multiprocessing ์ „ ์•Œ์•„์•ผ ํ•  ๊ฒƒ

๐Ÿ’ก CPU๊ฐ€ ๋ญ์ง€?

multiprocessing์„ ์‚ฌ์šฉํ•˜๊ธฐ ์ „์— ๊ธฐ๋ณธ์ ์œผ๋กœ ์•Œ์•„์•ผํ•  ๊ฒƒ๋“ค์ด ์žˆ๋‹ค. ๋‚œ ์ด ๋ถ€๋ถ„์„ ๋ชฐ๋ผ์„œ ์—„์ฒญ ์‚ฝ์งˆํ–ˆ๋‹ค๐Ÿ˜ž ๋‹ค๋ฅธ ์–ธ์–ด๋Š” ์ž˜ ๋ชจ๋ฅด๊ฒ ์ง€๋งŒ python์€ 1๊ฐœ์˜ cpu ์œ„์—์„œ ์ฝ”๋“œ๊ฐ€ ์‹คํ–‰๋œ๋‹ค. cpu ๋งŽ์ด ๋“ค์–ด๋ดค์„๊ฑฐ๋‹ค. python์—์„œ ์•„๋ž˜์™€ ๊ฐ™์ด ์ฝ”๋“œ๋ฅผ ์ž…๋ ฅํ•˜๋ฉด cpu ๊ฐฏ์ˆ˜๊ฐ€ ๋‚˜์˜จ๋‹ค. cpu๋Š” ์ปดํ“จํ„ฐ์˜ ๋จธ๋ฆฌ๋ผ๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋˜๋Š”๋ฐ ์šฐ๋ฆฌ๊ฐ€ ์ˆ˜์‹์„ ๊ณ„์‚ฐํ•  ๋•Œ ๋จธ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ์ปดํ“จํ„ฐ๊ฐ€ ์—ฐ์‚ฐํ•  ๋•Œ cpu๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. ์œ„์ฒ˜๋Ÿผ for๋ฌธ์— for๋ฌธ์„ ๋Œ๋ฆฌ๋Š” ๊ฒฝ์šฐ๋Š” cpu๊ฐ€ ์—ด์‹ฌํžˆ ์ผํ•˜๋Š” ๊ฒฝ์šฐ์ด๋‹ค. multiprocessing์—์„  pool์„ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

๐Ÿ’ก process๋Š” ๋ญ”๋ฐ?

multiprocessing documentation์„ ๋ณด๋ฉด multiprocessing์—๋Š” process์™€ pool์ด ์žˆ๋‹ค. pool์€ ๋‚ด๊ฐ€ ์œ„์—์„œ ๋งํ•œ ๊ฒƒ์ฒ˜๋Ÿผ cpu๋ฅผ ์—ฌ๋Ÿฌ๊ฐœ ๋Œ๋ฆฌ๊ธฐ ์œ„ํ•ด ์“ฐ๋Š” ๊ฒƒ์ด๊ณ (cpu bound๋ฅผ ์œ„ํ•œ ๊ฒƒ์ด๋ผ ํ•  ์ˆ˜ ์žˆ๋‹ค.) process๋Š” I/O bound๋ฅผ ์œ„ํ•œ ๊ฒƒ์ด๋‹ค. I/O bound๊ฐ€ ๋ญ”๋ฐ? I/O bound๋Š” input/output bound์ธ๋ฐ ์˜ˆ๋ฅผ ๋“ค๋ฉด ์ด๋Ÿฐ๊ฑฐ๋‹ค. ๋‚ด๊ฐ€ ์ฝ”๋”ฉ์„ ํ•˜๊ธฐ ์œ„ํ•ด pycharm์„ ์ผœ๋†“๋Š”๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์˜†์— ๊ตฌ๊ธ€๋ง์„ ์œ„ํ•ด ํฌ๋กฌ์„ ํ‚จ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์˜ค๋Š˜ ๋ฐฐ์šด ๊ฒƒ์„ ์ ์–ด๋†“๊ธฐ ์œ„ํ•ด ๋…ธ์…˜์„ ์ผœ๋†“๊ณ  ์ค‘๊ฐ„์ค‘๊ฐ„ ์‰ด๋•Œ ๊ธ€์„ ์“ฐ๊ธฐ ์œ„ํ•ด velog๋ฅผ ์ผœ๋†“๋Š”๋‹ค. ๋‚˜๋Š” ์ด์ œ ์ฝ”๋”ฉ์„ ์‹œ์ž‘ํ•  ๊ฒƒ์ด๋‹ค. ๋จผ์ € ์ฝ”๋”ฉ์„ ํ•œ๋‹ค. ๊ทธ๋Ÿฌ๋‹ค ๋ชจ๋ฅด๋Š”๊ฒŒ ์ƒ๊ฒผ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ๋ฐ”๋กœ ๊ตฌ๊ธ€๋ง์„ ํ•œ๋‹ค. ๊ทธ๋Ÿฌ๋‹ค ์•Œ์•„๋ƒˆ์œผ๋ฉด ๋‹ค์‹œ ์ฝ”๋”ฉ ๊ทธ๋Ÿฌ๋‹ค ์ง€์‹์„ ํ„ฐ๋“ํ–ˆ์œผ๋ฉด ๋…ธ์…˜์— ๋”ฐ๋กœ ์ •๋ฆฌ ์ด๋ ‡๊ฒŒ ํ•˜๋‚˜์˜ ๋ชธ๊ณผ ๋จธ๋ฆฌ๋กœ ์—ฌ๋Ÿฌ๊ฐœ๋ฅผ ์กฐ๊ธˆ์”ฉ ์ž˜๋ผ์„œ ๋™์‹œ์— ์‹คํ–‰ํ•˜๋Š” ๊ฒƒ์„ I/O bound๋ผ๊ณ  ํ•œ๋‹ค.

import multiprocessing

multiprocessing.cpu_count() #๋‚œ 10๊ฐœ

cpu bound๋Š” ํšŒ์‚ฌ์—์„œ 10๊ฐœ์˜ ์ž‘์—…์„ ์ง„ํ–‰ํ•˜๊ฒŒ ๋˜์—ˆ๋‹ค๋ฉด ์ง์› 2๋ช…ํ•œํ…Œ 5๊ฐœ์”ฉ ๋‚˜๋ˆ ์„œ ์ผ์„ ์‹œํ‚จ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ๋™์‹œ์— ๊ฐ์ž ์ž‘์—…์„ ์ง„ํ–‰ํ•˜๊ฒŒ ๋ ๊ฑฐ๊ณ  ๋งˆ์ง€๋ง‰์— ๋ณ‘ํ•ฉํ•˜๋ฉด ๋œ๋‹ค. ์ด ๊ฒƒ์„ cpu bound๋ผ๊ณ  ํ•œ๋‹ค. ๊ทธ๋ž˜์„œ ๊ฒฐ๊ตญ ๋‚œ for๋ฌธ์˜ for๋ฌธ์„ ๋Œ๋ ค์„œ ์—ฐ์‚ฐ์„ ํ•ด์•ผํ•˜๊ธฐ ๋•Œ๋ฌธ์— pool์„ ์‚ฌ์šฉํ•  ๊ฒƒ์ด๋‹ค.

 

โœจ multiprocessing ์‚ฌ์šฉ๋ฒ•

์šฐ์„  ์ œ์ผ ๋จผ์ € ํ•ด์•ผํ•˜๋Š” ๊ฒƒ์€ ๊ฐ cpu์— ๋‚˜๋ˆ ์ค„ ์ˆ˜ ์žˆ๊ฒŒ ๋ฐ์ดํ„ฐ๋ฅผ ๋น„์Šทํ•œ ์–‘์œผ๋กœ ์ชผ๊ฐœ๋Š” ๊ฒƒ์ด๋‹ค. ๋‚ด๊ฐ€ ์‚ฌ์šฉํ•  cpu์˜ ๊ฐฏ์ˆ˜๋ฅผ 10๊ฐœ๋ผ๊ณ  ํ•œ๋‹ค๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ๋ฐ์ดํ„ฐ๋ฅผ ์ชผ๊ฐค ์ˆ˜ ์žˆ๋‹ค. ์ฐธ๊ณ ๋กœ ์‚ฌ์šฉํ•  cpu๋ฅผ multiprocessing์—์„  worker๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค. second_df๋ฅผ ์ถœ๋ ฅํ•ด๋ณด๋ฉด 10๊ฐœ์˜ ๋ฆฌ์ŠคํŠธ๋กœ ๋˜์–ด์žˆ๊ณ  ๋ฆฌ์ŠคํŠธ ์•ˆ์—๋Š” ๋ฐ์ดํ„ฐํ”„๋ ˆ์ž„์ด ๋“ค์–ด์žˆ๋‹ค. 10๊ฐœ์˜ ๋ฆฌ์ŠคํŠธ ํ•˜๋‚˜์”ฉ 10๊ฐœ์˜ worker๋“ค์ด ์ผํ•˜๊ฒŒ ๋œ๋‹ค.

import numpy as np

max_worker = 10
second_df = np.array_split(second_df, max_worker)

์ด ํ›„์— pool์„ ์‹คํ–‰ํ•ด๋ณด์ž. ํ•˜๋‚˜์”ฉ ์„ค๋ช…ํ•˜์ž๋ฉด ๋จผ์ € Pool์„ ์—ด์–ด map์„ ์‹คํ–‰ํ•˜๋Š”๋ฐ ์—ฌ๊ธฐ์„œ ๊ถ๊ธˆํ•œ ์  ํ•œ๊ฐ€์ง€ partial์ด ๋ญ์ง€? partial์€ ๊ณ ์ •์‹œ์ผœ์ฃผ๋Š” ๊ฒƒ์ด๋‹ค. ๊ฒฐ๊ตญ ๋‚œ for๋ฌธ์— for๋ฌธ์„ ๋Œ๋ ค์•ผํ•œ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด map์—๋Š” ์ด๋Ÿฐ ์Œ๋“ค์ด ๋“ค์–ด๊ฐ€์•ผ ํ•œ๋‹ค. first_df์˜ ๊ฐฏ์ˆ˜๊ฐ€ 3000, second_df์˜ ๊ฐฏ์ˆ˜๊ฐ€ 8000์ด๋ผํ•  ๋•Œ (first_seq1, second_seq1), (first_seq1, second_seq2), (first_seq1, second_seq3), …, (first_seq3000, second_seq7999), (first_seq3000, second_seq8000) ์ด๋ ‡๊ฒŒ cross mapping์œผ๋กœ ๋“ค์–ด๊ฐ€์•ผํ•œ๋‹ค. ์ด ๋ถ€๋ถ„์„ ๋” ํšจ์œจํ™”ํ•˜๋Š” ๊ฒƒ์ด partial์ด๋‹ค. first_df๋Š” ๊ณ ์ •ํ•ด์ฃผ๋ฉด second_df๊ฐ€ ๋ฐ˜๋ณตํ•˜๋Š” ๋งŒํผ ์•Œ์•„์„œ ๋ฐ˜๋ณต์‹œ์ผœ์ค€๋‹ค. ์ผ๋ฐ˜์ ์ธ mapํ•จ์ˆ˜์™€ ๋น„์Šทํ•˜๊ฒŒ ๋“ค์–ด๊ฐ€๋ฉด ๋œ๋‹ค. ๊ทธ๋Ÿฌ๊ณ  ๊ฐ worker๋“ค์ด ์—ด์‹ฌํžˆ ๊ณ„์‚ฐํ•œ ๊ฒƒ์ด ์ชผ๊ฐœ์ ธ์„œ results์— ์ €์žฅ๋œ๋‹ค. ๊ทธ๋ž˜์„œ chain.from_iterable๋กœ shape์„ ์ค„์—ฌ์ค€๋‹ค.

with Pool(processes=max_worker) as pool:
    results = pool.map(partial(calculate, first_df), second_df)
df = pd.DataFrame(list(chain.from_iterable(results))

๋ชจ๋“  ์ฝ”๋“œ๊ฐ€ ์™„์„ฑ๋˜์—ˆ๋‹ค. ์ฝ”๋“œ๋ฅผ ํ•ฉ์ณ๋ณด๋ฉด ์ด๋ ‡๊ฒŒ ๋œ๋‹ค.

import numpy as np
import multiprocessing
from functools import partial
from itertools import chain

max_worker = 10

def calculate(first_df, second_df):
    results = []
    for first_index, first_seq in first_df.values:
        for second_index, second_seq in second_df.values:
            results.append(first_seq+second_seq)
            
    return results

second_df = np.array_split(second_df, max_worker)
with Pool(processes=max_worker) as pool:
    results = pool.map(partial(calculate, first_df), second_df)
df = pd.DataFrame(list(chain.from_iterable(results))

์ถ”๊ฐ€๋กœ tqdm๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ๋‚ด ์ฝ”๋“œ์—์„  tqdm(first_df.values)๋กœ chopํ•˜๋ฉด ๋œ๋‹ค.

 

โœจ ์ฃผ์˜ํ•  ์ 

multiprocessing์„ ์‚ฌ์šฉํ•  ๋• ๊ผญ ์•„๋ž˜์˜ ์ฝ”๋“œ์™€ ํ•จ๊ป˜ ์จ์•ผํ•œ๋‹ค๊ณ  ์ ํ˜€์žˆ๋‹ค. ์จ์•ผํ•˜๋Š” ์ด์œ ๋Š” module์„ importํ•  ๋•Œ ๋ฏธ๋ฆฌ ์‹คํ–‰๋˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด์„œ์ด๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ ๊ตฌ๊ธ€๋งํ•˜๋ฉด ๋งŽ์ด ๋‚˜์˜จ๋‹ค.

if __name__ == '__main__'

์ฐธ๊ณ  ์ž๋ฃŒ

์ตœ๊ทผ์— ์˜ฌ๋ผ์˜จ ๊ธ€
ยซ   2025/07   ยป
์ผ ์›” ํ™” ์ˆ˜ ๋ชฉ ๊ธˆ ํ† 
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
Total
Today
Yesterday