다중 처리 라이브러리가있는 큰 데이터 구조에 대해 간단한 계산을하려고합니다. 그것은 내 논문을 위해 필요한 것입니다. 그러니 제발 나를 조심성 거리지 마십시오.다중 처리 Python 라이브러리의 데이터 구조가 느리다
여러 개의 "worker", "threads", "processes"에 대한 계산을 나누거나 원하는대로 호출하기로 결정했을 때 필자는 파이썬 문서를보고 필요한 모듈을 찾은 다음 두 개의 모듈 인 'threading '및'다중 처리 '. 독서 후, 나는 그것이 필요로하는 것처럼 보이기 때문에 '다중 처리'를 사용하기로 결정했습니다.
문제는 여러 작업자 (프로세스)에서 계산이 훨씬 느립니다. 첫 번째 생각은 입력 데이터의 크기와 관련이 있습니다. 작은 데이터의 경우 실행중인 스레드의 '비용'이 단순한 계산보다 훨씬 크다는 것을 이해합니다. 그러나 큰 구조의 경우 효율성이 높아야합니다.
나는 소수의 프로세스로 계산할 때 계산 알고리즘을 사용하는 것보다 계산 알고리즘 (예 : 2D Rosenbrock)이 반복 알고리즘에 비해 몇 배 빨랐다. 계산은 100,000 개의 튜플에 대해 수행됩니다.
나는 또한 다중 처리를 주목했다 .Queue 액세스는 collections.deque에 대한 액세스보다 몇 배나 느리지 만 실제로이 계산을 "공유 메모리"또는 비슷한 것으로해야 할 필요가있다.
어디에서 문제를 설명 할 수 있습니까? 파이썬이 그렇게 효율적이기 때문에 다중 프로세스로 계산할 가치가 없습니까? 적절한 데이터 구조를 사용합니까? 멀티 프로세싱에 대한 인식에서 뭔가를 바꿀 수 있습니까? 또는 어쩌면 나는 나쁜 방법으로 그것을 측정합니까? 나는 속도를 낼 수있는 방법에 대해 정말로 고마워한다.
#!/usr/bin/python
import multiprocessing
from timeit import default_timer as timer
import random
import collections
class Worker(multiprocessing.Process):
counter = 0
def __init__(self, idx, from_queue):
super(Worker, self).__init__()
self.from_queue = from_queue
self.idx = idx
def run(self):
print ("Worker started", self.idx)
for data in iter(self.from_queue.pop, None):
x_1, x_2 = data
result = 100*(x_2-x_1**2)**2 + (1-x_1)**2
def main():
tuple_counts = 100000
min_x = -5
max_x = 5
tuples = multiprocessing.Queue()
for _ in range(tuple_counts):
my_tuple = {random.uniform(min_x, max_x), random.uniform(min_x, max_x)}
tuples.put(my_tuple)
cores = multiprocessing.cpu_count() - 1
pops = []
for _ in range(cores):
pop = collections.deque()
pops.append(pop)
for pop in pops:
for _ in range(int(tuple_counts/cores)):
pop.append(tuples.get())
for _ in range(int(tuple_counts % cores)):
pops[_].append(tuples.get())
for pop in pops:
pop.append(None)
workers = []
process_time = 0
process_time_start = timer()
for i in range(multiprocessing.cpu_count()-1):
worker = Worker(i, pops[i])
workers.append(worker)
worker.start()
for worker in workers:
worker.join()
process_time_stop = timer()
process_time += (process_time_stop-process_time_start)
print("process_time", process_time)
iter_time = 0
iter_timer_start = timer()
for _ in range(tuples.qsize()):
x_1, x_2 = tuples.qet()
result = 100*(x_2-x_1**2)**2 + (1-x_1)**2
iter_timer_stop = timer()
iter_time += (iter_timer_stop-iter_timer_start)
print("iter_time", iter_time)
if __name__ == "__main__":
main()
데이터를 전달하는 것은 일반적으로 피해야 할 대상입니다. 각 작업자에게 처리 할 튜플의 수를 알려주고 무작위 튜플을 독립적으로 생성하고 처리하게하는 것은 무엇입니까? – Blender
내가 이해할 지 모르겠다. 어떻게해야 각 근로자에게 계산을해야한다고 말하면서 100 명의 로젠 브록을 말할 수 있습니까? 물론 논쟁으로 전달하거나 다른 것을 의미 할 수 있습니까? 모든 작업자에 대해 하나의 대기열을 사용하고 있었을 때 나는 그것이 더 느렸다 고 생각합니다. – Tatarinho
큐는 부모 프로세스에서 자식 프로세스로 전달하기 위해 생성 한 모든 튜플을 직렬화 및 비 직렬화해야합니다. 직렬화 및 직렬화 해제는 단순히 결과를 계산하는 것보다 시간이 더 걸릴 것입니다. 일반적으로 이와 같이 데이터를 전달하지 않는 것이 가장 좋습니다. 작업자에게 생성 할 튜플 수를 알려주는 단일 정수를 작업자에게 전달하면됩니다. – Blender