2013-06-29 31 views
17

Câu hỏi đầu tiên là sự khác biệt giữa Giá trị và Trình quản lý().Biến chia sẻ trong đa xử lý của python

Thứ hai, có thể chia sẻ biến số nguyên mà không sử dụng Giá trị không? Dưới đây là mã mẫu của tôi. Những gì tôi muốn là nhận được một dict với một giá trị của số nguyên, không phải giá trị. Những gì tôi đã làm chỉ là thay đổi tất cả sau quá trình. Có cách nào dễ hơn không?

from multiprocessing import Process, Manager 

def f(n): 
    n.value += 1 

if __name__ == '__main__': 
    d = {} 
    p = [] 

    for i in range(5): 
     d[i] = Manager().Value('i',0) 
     p.append(Process(target=f, args=(d[i],))) 
     p[i].start() 

    for q in p: 
     q.join() 

    for i in d: 
     d[i] = d[i].value 

    print d 
+0

Có liên quan: http://eli.thegreenplace.net/2012/01/04/shared-counter-with-pythons-multiprocessing –

Trả lời

19

Khi bạn sử dụng Value bạn nhận được một đối tượng ctypes trong bộ nhớ chia sẻ rằng theo mặc định được đồng bộ sử dụng RLock. Khi bạn sử dụng Manager, bạn sẽ nhận được đối tượng SynManager kiểm soát quy trình máy chủ cho phép các giá trị đối tượng bị thao tác bởi các quy trình khác. Bạn có thể tạo nhiều proxy bằng cùng một người quản lý; không có nhu cầu để tạo ra một người quản lý mới trong vòng lặp của bạn:

manager = Manager() 
for i in range(5): 
    new_value = manager.Value('i', 0) 

Các Manager có thể được chia sẻ trên máy tính, trong khi Value được giới hạn trong một máy tính. Value sẽ nhanh hơn (chạy mã bên dưới để xem), vì vậy tôi nghĩ bạn nên sử dụng điều đó trừ khi bạn cần hỗ trợ các đối tượng tùy ý hoặc truy cập chúng qua mạng.

import time 
from multiprocessing import Process, Manager, Value 

def foo(data, name=''): 
    print type(data), data.value, name 
    data.value += 1 

if __name__ == "__main__": 
    manager = Manager() 
    x = manager.Value('i', 0) 
    y = Value('i', 0) 

    for i in range(5): 
     Process(target=foo, args=(x, 'x')).start() 
     Process(target=foo, args=(y, 'y')).start() 

    print 'Before waiting: ' 
    print 'x = {0}'.format(x.value) 
    print 'y = {0}'.format(y.value) 

    time.sleep(5.0) 
    print 'After waiting: ' 
    print 'x = {0}'.format(x.value) 
    print 'y = {0}'.format(y.value) 

Để tóm tắt:

  1. Sử dụng Manager để tạo ra nhiều đối tượng chia sẻ, bao gồm dicts và danh sách. Sử dụng Manager để chia sẻ dữ liệu giữa các máy tính trên mạng.
  2. Sử dụng Value hoặc Array khi không cần chia sẻ thông tin trên mạng và các loại trong ctypes là đủ cho nhu cầu của bạn.
  3. Value nhanh hơn Manager.

Warning

Bằng cách này, chia sẻ dữ liệu qua các quy trình/đề nên tránh nếu có thể. Đoạn mã trên có thể chạy như mong đợi, nhưng tăng thời gian để thực hiện foo và mọi thứ sẽ trở nên kỳ lạ. So sánh các bên trên với:

def foo(data, name=''): 
    print type(data), data.value, name 
    for j in range(1000): 
     data.value += 1 

Bạn cần có Lock để làm việc này hoạt động chính xác.

Tôi không đặc biệt am hiểu về tất cả những điều này, vì vậy có thể một người khác sẽ đến và cung cấp thông tin chi tiết hơn. Tôi nghĩ tôi sẽ đóng góp một câu trả lời vì câu hỏi đó không được chú ý. Hy vọng rằng sẽ giúp một chút.

+0

chúng ta có thể thêm bất kỳ giá trị nào vào mảng không? Tôi không thể thêm bất kỳ giá trị nào vào Array. – user2435611

+2

@ user2435611, ['Array'] (http://docs.python.org/2/library/multiprocessing.html#multiprocessing.Array) sẽ cung cấp cho bạn một mảng ctypes được chia sẻ. Bạn cần quyết định loại dữ liệu nào bạn đang lưu trữ trước và cung cấp [loại mã] (http://docs.python.org/2/library/array.html#module-array). Ví dụ, 'a = Array ('c', 10)' tạo một mảng các chuỗi ký tự có độ dài 10. Các mục mới có thể được thêm vào mảng như sau: 'a [0] = 'b''.Bạn không thể thêm giá trị * any * vào một mảng, xem [danh sách các loại mã] (http://docs.python.org/2/library/array.html#module-array). – ChrisP

+0

Vì vậy, chúng ta nên quyết định kích thước của mảng trước và không thể mở rộng nó? nếu vậy, tốt hơn là tôi nên sử dụng manager.list(). Cảm ơn bạn đã giúp đỡ :) – user2435611

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