2014-11-01 24 views
5

Tôi đang sử dụng mô-đun đa xử lý Python để tạo một nhóm quy trình và giao công việc cho nó.Quá trình xử lý đa xử lý Python

Tôi đã tạo ra 4 quy trình và phân công 2 công việc nhưng cố gắng để hiển thị con số quá trình của họ, nhưng trong màn hình Tôi chỉ thấy số một quá trình "6952" ... nên không nó in số 2 quá trình

from multiprocessing import Pool 
from time import sleep 

def f(x): 
    import os 
    print "process id = " , os.getpid() 
    return x*x 

if __name__ == '__main__': 
    pool = Pool(processes=4)    # start 4 worker processes 

    result = pool.map_async(f, (11,)) #Start job 1 
    result1 = pool.map_async(f, (10,)) #Start job 2 
    print "result = ", result.get(timeout=1) 
    print "result1 = ", result1.get(timeout=1) 

Kết quả: -

result = process id = 6952 
process id = 6952 
[121] 
result1 = [100] 
+0

Bạn đang sử dụng Windows? – dano

+0

@ dano-yes ....., – user1050619

Trả lời

2

Nó sắp hết thời gian. Windows cần tạo ra 4 quy trình trong Pool, sau đó cần khởi động, khởi tạo và chuẩn bị để tiêu thụ từ Queue. Trên Windows, điều này đòi hỏi mỗi quy trình con phải nhập lại mô-đun __main__ và đối với các trường hợp Queue được sử dụng nội bộ theo số Pool để được bỏ tạm dừng ở mỗi trẻ. Việc này mất một lượng thời gian không nhỏ. Đủ lâu, trên thực tế, khi cả hai cuộc gọi map_async() của bạn được thực thi trước khi tất cả các quy trình trong Pool đều được thiết lập và hoạt động. Bạn có thể thấy điều này nếu bạn thêm một số lần theo các chức năng chạy bởi mỗi công nhân trong Pool:

while maxtasks is None or (maxtasks and completed < maxtasks): 
    try: 
     print("getting {}".format(current_process())) 
     task = get() # This is getting the task from the parent process 
     print("got {}".format(current_process())) 

Output:

getting <ForkServerProcess(ForkServerPoolWorker-1, started daemon)> 
got <ForkServerProcess(ForkServerPoolWorker-1, started daemon)> 
process id = 5145 
getting <ForkServerProcess(ForkServerPoolWorker-1, started daemon)> 
got <ForkServerProcess(ForkServerPoolWorker-1, started daemon)> 
process id = 5145 
getting <ForkServerProcess(ForkServerPoolWorker-1, started daemon)> 
result = [121] 
result1 = [100] 
getting <ForkServerProcess(ForkServerPoolWorker-2, started daemon)> 
getting <ForkServerProcess(ForkServerPoolWorker-3, started daemon)> 
getting <ForkServerProcess(ForkServerPoolWorker-4, started daemon)> 
got <ForkServerProcess(ForkServerPoolWorker-1, started daemon)> 

Như bạn thấy, Worker-1 bắt đầu lên và tiêu thụ cả nhiệm vụ trước khi người lao động 2-4 bao giờ cố gắng tiêu thụ từ Queue. Nếu bạn thêm một cuộc gọi sleep sau khi bạn nhanh chóng Pool trong quá trình chính, nhưng trước khi gọi map_async, bạn sẽ thấy quá trình khác nhau xử lý mỗi yêu cầu:

getting <ForkServerProcess(ForkServerPoolWorker-1, started daemon)> 
getting <ForkServerProcess(ForkServerPoolWorker-2, started daemon)> 
getting <ForkServerProcess(ForkServerPoolWorker-3, started daemon)> 
getting <ForkServerProcess(ForkServerPoolWorker-4, started daemon)> 
# <sleeping here> 
got <ForkServerProcess(ForkServerPoolWorker-1, started daemon)> 
process id = 5183 
got <ForkServerProcess(ForkServerPoolWorker-2, started daemon)> 
process id = 5184 
getting <ForkServerProcess(ForkServerPoolWorker-1, started daemon)> 
getting <ForkServerProcess(ForkServerPoolWorker-2, started daemon)> 
result = [121] 
result1 = [100] 
got <ForkServerProcess(ForkServerPoolWorker-3, started daemon)> 
got <ForkServerProcess(ForkServerPoolWorker-4, started daemon)> 
got <ForkServerProcess(ForkServerPoolWorker-1, started daemon)> 
got <ForkServerProcess(ForkServerPoolWorker-2, started daemon)> 

(Lưu ý rằng thêm "getting/"got" báo cáo mà bạn nhìn thấy là các sentinels được gửi đến từng quá trình để đóng chúng một cách duyên dáng).

Sử dụng Python 3.x trên Linux, tôi có thể tạo lại hành vi này bằng các ngữ cảnh 'spawn''forkserver', nhưng không phải 'fork'. Có lẽ bởi vì forking các tiến trình con nhanh hơn nhiều so với sinh sản chúng và làm một tái nhập khẩu của __main__.

0

Nó in 2 id quá trình.

result = process id = 6952 <=== process id = 6952 
process id = 6952 <=== process id = 6952 
[121] 
result1 = [100] 

Điều này là do quy trình công nhân của bạn đã hoàn tất nhanh chóng và sẵn sàng xử lý yêu cầu khác.

result = pool.map_async(f, (11,)) #Start job 1 
result1 = pool.map_async(f, (10,)) #Start job 2 

Trong mã trên, nhân viên của bạn đã hoàn thành công việc và quay lại hồ bơi và sẵn sàng hoàn thành công việc 2. Điều này có thể xảy ra vì nhiều lý do. Những người thường xuyên nhất là công nhân đang bận, hoặc chưa sẵn sàng.

Dưới đây là ví dụ mà chúng tôi sẽ có 4 công nhân, nhưng chỉ một trong số họ sẽ sẵn sàng ngay lập tức. Vì vậy chúng ta biết cái nào sẽ thực hiện công việc.

# https://gist.github.com/dnozay/b2462798ca89fbbf0bf4 

from multiprocessing import Pool,Queue 
from time import sleep 

def f(x): 
    import os 
    print "process id = " , os.getpid() 
    return x*x 

# Queue that will hold amount of time to sleep 
# for each worker in the initialization 
sleeptimes = Queue() 
for times in [2,3,0,2]: 
    sleeptimes.put(times) 

# each worker will do the following init. 
# before they are handed any task. 
# in our case the 3rd worker won't sleep 
# and get all the work. 
def slowstart(q): 
    import os 
    num = q.get() 
    print "slowstart: process id = {0} (sleep({1}))".format(os.getpid(),num) 
    sleep(num) 

if __name__ == '__main__': 
    pool = Pool(processes=4,initializer=slowstart,initargs=(sleeptimes,)) # start 4 worker processes 
    result = pool.map_async(f, (11,)) #Start job 1 
    result1 = pool.map_async(f, (10,)) #Start job 2 
    print "result = ", result.get(timeout=3) 
    print "result1 = ", result1.get(timeout=3) 

dụ:

$ python main.py 
slowstart: process id = 97687 (sleep(2)) 
slowstart: process id = 97688 (sleep(3)) 
slowstart: process id = 97689 (sleep(0)) 
slowstart: process id = 97690 (sleep(2)) 
process id = 97689 
process id = 97689 
result = [121] 
result1 = [100] 
+0

gist tại https://gist.github.com/dnozay/b2462798ca89fbbf0bf4 – dnozay

Các vấn đề liên quan