수색…


소개

대부분의 프로그램은 한 번에 하나의 프로세스 만 실행하여 한 줄씩 실행됩니다. 스레드를 사용하면 여러 프로세스가 서로 독립적으로 흐름 할 수 있습니다. 다중 프로세서로 스레딩하면 프로그램이 여러 프로세스를 동시에 실행할 수 있습니다. 이 주제는 파이썬에서 스레드의 구현과 사용법을 설명합니다.

전역 통역관 잠금

전역 인터프리터 잠금 (Global Interpreter Lock) 으로 인해 파이썬 다중 스레딩 성능이 저하 될 수 있습니다. 즉, 파이썬 프로그램에서 여러 스레드를 가질 수 있다고해도 CPU 수에 관계없이 한 번에 하나의 바이트 코드 명령어 만 병렬로 실행할 수 있습니다.

따라서 네트워크 액세스와 같은 외부 이벤트로 작업이 차단되는 경우 멀티 스레딩이 매우 효과적 일 수 있습니다.

import threading
import time


def process():
    time.sleep(2)


start = time.time()
process()
print("One run took %.2fs" % (time.time() - start))


start = time.time()
threads = [threading.Thread(target=process) for _ in range(4)]
for t in threads:
    t.start()
for t in threads:
    t.join()
print("Four runs took %.2fs" % (time.time() - start))

# Out: One run took 2.00s
# Out: Four runs took 2.00s

process 를 실행 process 데 2 초가 걸렸지 만 4 개의 프로세스를 함께 실행하면 총 2 초의 시간이 소요되어 병렬로 효과적으로 실행될 수있었습니다.

그러나 집중적 인 계산이 많은 계산과 같이 파이썬 코드에서 수행되는 경우의 멀티 스레딩은 많은 향상을 가져 오지 않으며 병렬로 실행하는 것보다 느려질 수 있습니다.

import threading
import time


def somefunc(i):
    return i * i

def otherfunc(m, i):
    return m + i

def process():
    for j in range(100):
        result = 0
        for i in range(100000):
            result = otherfunc(result, somefunc(i))


start = time.time()
process()
print("One run took %.2fs" % (time.time() - start))


start = time.time()
threads = [threading.Thread(target=process) for _ in range(4)]
for t in threads:
    t.start()
for t in threads:
    t.join()
print("Four runs took %.2fs" % (time.time() - start))

# Out: One run took 2.05s
# Out: Four runs took 14.42s

후자의 경우 여러 프로세스가 동시에 여러 명령어를 실행할 수 있기 때문에 다중 처리가 효과적 일 수 있습니다.

import multiprocessing
import time


def somefunc(i):
    return i * i

def otherfunc(m, i):
    return m + i

def process():
    for j in range(100):
        result = 0
        for i in range(100000):
            result = otherfunc(result, somefunc(i))


start = time.time()
process()
print("One run took %.2fs" % (time.time() - start))


start = time.time()
processes = [multiprocessing.Process(target=process) for _ in range(4)]
for p in processes:
    p.start()
for p in processes:
    p.join()
print("Four runs took %.2fs" % (time.time() - start))

# Out: One run took 2.07s
# Out: Four runs took 2.30s

여러 스레드에서 실행 중

threading.Thread 를 사용하여 다른 스레드에서 함수를 실행하십시오.

import threading
import os

def process():
    print("Pid is %s, thread id is %s" % (os.getpid(), threading.current_thread().name))

threads = [threading.Thread(target=process) for _ in range(4)]
for t in threads:
    t.start()
for t in threads:
    t.join()
    
# Out: Pid is 11240, thread id is Thread-1
# Out: Pid is 11240, thread id is Thread-2
# Out: Pid is 11240, thread id is Thread-3
# Out: Pid is 11240, thread id is Thread-4

여러 프로세스에서 실행

multiprocessing.Process 를 사용하여 다른 프로세스에서 함수를 실행하십시오. 인터페이스는 threading.Thread 와 유사합니다.

import multiprocessing
import os

def process():
    print("Pid is %s" % (os.getpid(),))

processes = [multiprocessing.Process(target=process) for _ in range(4)]
for p in processes:
    p.start()
for p in processes:
    p.join()
    
# Out: Pid is 11206
# Out: Pid is 11207
# Out: Pid is 11208
# Out: Pid is 11209

스레드 간 상태 공유

모든 스레드가 동일한 프로세스에서 실행되므로 모든 스레드가 동일한 데이터에 액세스 할 수 있습니다.

그러나 공유 데이터에 대한 동시 액세스는 동기화 문제를 피하기 위해 잠금으로 보호되어야합니다.

import threading

obj = {}
obj_lock = threading.Lock()

def objify(key, val):
    print("Obj has %d values" % len(obj))
    with obj_lock:
        obj[key] = val
    print("Obj now has %d values" % len(obj))

ts = [threading.Thread(target=objify, args=(str(n), n)) for n in range(4)]
for t in ts:
    t.start()
for t in ts:
    t.join()
print("Obj final result:")
import pprint; pprint.pprint(obj)

# Out: Obj has 0 values
# Out:  Obj has 0 values
# Out: Obj now has 1 values
# Out: Obj now has 2 valuesObj has 2 values
# Out: Obj now has 3 values
# Out: 
# Out:  Obj has 3 values
# Out: Obj now has 4 values
# Out: Obj final result:
# Out: {'0': 0, '1': 1, '2': 2, '3': 3}

프로세스 간 상태 공유

다른 프로세스에서 실행되는 코드는 기본적으로 동일한 데이터를 공유하지 않습니다. 그러나 multiprocessing 모듈에는 여러 프로세스에서 값을 공유하는 데 도움이되는 기본 요소가 포함되어 있습니다.

import multiprocessing

plain_num = 0
shared_num = multiprocessing.Value('d', 0)
lock = multiprocessing.Lock()

def increment():
    global plain_num
    with lock:
        # ordinary variable modifications are not visible across processes
        plain_num += 1
        # multiprocessing.Value modifications are
        shared_num.value += 1

ps = [multiprocessing.Process(target=increment) for n in range(4)]
for p in ps:
    p.start()
for p in ps:
    p.join()

print("plain_num is %d, shared_num is %d" % (plain_num, shared_num.value))

# Out: plain_num is 0, shared_num is 4



Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow