2013-09-28 191 views
7

Tôi đang cố triển khai tính năng đa xử lý này tutorial cho mục đích của riêng tôi. Lúc đầu, tôi nghĩ rằng nó đã không quy mô tốt, nhưng khi tôi thực hiện một ví dụ tái sản xuất tôi thấy rằng nếu danh sách các mục đi trên 124, có vẻ như không bao giờ trả lời một câu trả lời. Tại x = 124 nó chạy trong .4 giây, nhưng khi tôi đặt nó là x = 125 nó không bao giờ kết thúc. Tôi đang chạy Python 2.7 trên Windows 7.Xử lý đa xử lý Python> = 125 danh sách không bao giờ kết thúc

from multiprocessing import Lock, Process, Queue, current_process 
import time 

class Testclass(object): 
    def __init__(self, x): 
     self.x = x 

def toyfunction(testclass): 
    testclass.product = testclass.x * testclass.x 
    return testclass 


def worker(work_queue, done_queue): 
    try: 
     for testclass in iter(work_queue.get, 'STOP'): 
      print(testclass.counter) 
      newtestclass = toyfunction(testclass) 
      done_queue.put(newtestclass) 

    except: 
     print('error') 

    return True 

def main(x): 

    counter = 1 

    database = [] 
    while counter <= x: 
     database.append(Testclass(10)) 
     counter += 1 
     print(counter) 



    workers = 8 
    work_queue = Queue() 
    done_queue = Queue() 
    processes = [] 

    start = time.clock() 
    counter = 1 

    for testclass in database: 
     testclass.counter = counter 
     work_queue.put(testclass) 
     counter += 1 
     print(counter) 


    print('items loaded') 
    for w in range(workers): 
     p = Process(target=worker, args=(work_queue, done_queue)) 
     p.start() 
     processes.append(p) 
     work_queue.put('STOP') 

    for p in processes: 
     p.join() 

    done_queue.put('STOP') 

    newdatabase = [] 
    for testclass in iter(done_queue.get, 'STOP'): 
     newdatabase.append(testclass) 

    print(time.clock()-start) 
    print("Done") 
    return(newdatabase) 

if __name__ == '__main__': 
    database = main(124) 
    database2 = main(125) 
+0

Nó phù hợp với tôi. – Veedrac

+0

ông đã đăng một câu hỏi khác ở đây làm việc cho tôi. http://stackoverflow.com/questions/19070638/python-multiprocessing-ioerror-errno-232-the-pipe-is-being-closed#comment28188856_19070638 –

+0

Tôi đã khắc phục sự cố trong bài đăng khác. Tôi đã thử chạy mã trên trên cả hai máy tính của tôi và trên cả hai nó treo ở cuối khi 'x = 125' và không bao giờ in Done. – Michael

Trả lời

6

OK! Từ the docs:

Warning Như đã đề cập ở trên, nếu một quá trình con đã đặt mục trên một hàng đợi (và nó có không sử dụng JoinableQueue.cancel_join_thread), sau đó quá trình đó sẽ không chấm dứt cho đến khi tất cả mục đệm đã được đỏ mặt vào đường ống. Điều này có nghĩa là nếu bạn cố gắng tham gia quá trình đó, bạn có thể bị bế tắc trừ khi bạn chắc chắn rằng tất cả các mục đã được đưa vào hàng đợi đã được tiêu thụ. Tương tự, nếu quy trình con không phải là daemon thì quá trình cha mẹ có thể treo khi thoát khi nó cố gắng để tham gia tất cả các trẻ không daemonemon của nó. Lưu ý rằng hàng đợi được tạo bằng cách sử dụng trình quản lý không không có vấn đề này. Xem Hướng dẫn lập trình.

Như tôi đã nói trong một chú thích trước đó, những nỗ lực mã để .join() quá trình trước các done_queue Queue được để ráo nước - và đó là sau khi thay đổi mã trong một cách sôi nổi để chắc chắn done_queue được để ráo nước trước khi .join() 'ing, mã hoạt động tốt cho một triệu mục.

Vì vậy, đây là trường hợp lỗi thí điểm, mặc dù khá mơ hồ. Về lý do tại sao hành vi phụ thuộc vào số lượng được chuyển đến main(x), điều này không thể đoán trước: nó phụ thuộc vào cách đệm được thực hiện nội bộ. Vui vẻ như vậy ;-)

+0

Bạn có đề xuất bất kỳ công việc cụ thể nào cho mã bên trên không? Có cách nào khác để mọi người thường lấy lại thành phẩm từ hàng đợi không? – Michael

+3

Tôi đã giải thích trong một bình luận như thế nào tôi "cố định" này: Thay đổi 'công nhân()' để làm 'done_queue.put ('STOP')' ngay trước khi nó kết thúc. Thay đổi sự lặp lại của chương trình chính trên 'done_queue' để đếm số lần nó thấy' 'STOP'' - nó được thực hiện khi nó thấy 'công nhân' của chúng. Di chuyển '.join()' s ** sau ** lần lặp qua 'done_queue' được hoàn tất. –