pthon의subprocess에서 간단하게 병렬 실행

・대량의 데이터를 병행 처리하기를 희망한다.
• 모처럼 CPU에 핵심이 많아서 효율적으로 활용하고 싶어요.
• 각본을 썼지만 병행해서 다시 쓸 여지가 없다.
많이 조사했어,subprocess.Popen()을 사용하는 방법이 간단해 보이기 때문에 실험을 진행했다.
참고 문장
https://qiita.com/HidKamiya/items/e192a55371a2961ca8a4

운행 환경 및 부하 테스트용 샘플 코드


Windows 10 (64bit)
Python 3.7.6
CPU는 Ryzen93950X와 같은 환경입니다.

다음 코드로 실험을 진행한다.
(명령행 매개 변수에 의해 지정된 피보나치 수열의 다음 두 자리만 표시됩니다.)
fib_sample.py
import sys

def fib(n):
    a, b = 0, 1
    for i in range(n):
        a, b = b, a + b
    return a

if __name__ == "__main__":
    num = int(sys.argv[1])
    result = fib(num)
    print("n = {0}, result % 100 = {1}".format(num, result % 100))
예를 들어 python fib_sample.py 10000대로 실행하면 n = 10000, result % 100 = 75끝으로 표시됩니다.

순차적으로 집행하다


우선subprocess입니다.run () 순서로 실행해 봅시다.
pythn을 실행하기 위해 subprocess.run(['python', r".\fib_sample.py", str(500000 + i)])에 파라미터를 제공합니다.명령줄 매개 변수 500000에서 500063으로 64회 변경 후
batch_sequential.py
from time import time
import subprocess

start=time()

loop_num = 64
for i in range(loop_num):
    subprocess.run(['python', r".\fib_sample.py", str(500000 + i)])

end=time()
print("%f sec" %(end-start))
> python .\batch_sequential.py
n = 500000, result % 100 = 25
n = 500001, result % 100 = 26
n = 500002, result % 100 = 51
(中略)
n = 500061, result % 100 = 86
n = 500062, result % 100 = 31
n = 500063, result % 100 = 17
130.562213 sec
2분 낫다.
물론 CPU 코어도 전혀 사용하지 않았다.

병렬 실행


같은 처리를 하다.Popen()을 사용하여 병렬 실행을 시도합니다.subprocess.Popen은 subprocess입니다.run ()과 다른 생성 과정의 끝을 기다리지 않습니다.
다음 코드는 max-프로세스가 지정한 수량에 따라 실행 → 모두 끝날 때까지 기다리기 → 다음 프로세스가 실행 →.반복하고 있다.
batch_parallel.py
from time import time
import subprocess

start=time()

#並列プロセス実行数の最大値
max_process = 16
proc_list = []

loop_num = 64
for i in range(loop_num):
    proc = subprocess.Popen(['python', r".\fib_sample.py", str(500000 + i)])
    proc_list.append(proc)
    if (i + 1) % max_process == 0 or (i + 1) == loop_num:
        #max_process毎に、全プロセスの終了を待つ
        for subproc in proc_list:
            subproc.wait()
        proc_list = []

end=time()
print("%f sec" %(end-start))
Ryzen 3950X의 물리적 코어 수를 기준으로 16개의 결과를 병렬로 수행합니다.
> python .\batch_parallel.py
n = 500002, result % 100 = 51
n = 500004, result % 100 = 28
n = 500001, result % 100 = 26
(中略)
n = 500049, result % 100 = 74
n = 500063, result % 100 = 17
n = 500062, result % 100 = 31
8.165289 sec
병행 집행으로 처리가 끝난 순서가 분산되었다.
130.562초→8.165초로 속도가 거의 16배에 달했다.
모든 핵심이 사용되고 정확하게 병행 집행될 수 있음을 알 수 있다.

그나저나 물리적 핵심수는 물론이고 논리적 핵심수에 맞춰 32개를 병행하는 것도 이르지 않다.오히려 지각할 때가 있다.
병렬 실행 수를 변경합니다. 각각 3회 실행할 때의 평균 실행 시간은 아래 그림과 같습니다.

백그라운드에서 다양한 앱을 실행했기 때문에 정확하지는 않지만, 성향은 옳다고 생각한다.

총결산


간단하게 고속화할 수도 있다.
상기 코드라면 병행 실행을 시작한 후 가장 긴 프로세스가 끝날 때까지 기다리기 때문에 공교롭게도 처리 시간이 길면 끝날 때까지 기다리는 비용이 커진다.나는 원래 각 프로그램의 실행이 끝난 후에 바로 다음 프로그램을 시작하고 병행수를 일정한 코드로 바꾸어야 한다고 생각한다.
그러나 실제 목적은 같은 길이의 대량의 데이터 파일을 같은 신호 처리에 응용하기 위해서였기 때문에 실행 시간이 대체로 같을 것으로 예상되어 얼떨떨해졌다.어쨌든 단순 고속화의 목적을 실현했기 때문에 만족스럽다.

좋은 웹페이지 즐겨찾기