2011-01-13 28 views
35

Tôi đang tìm một câu trả lời cuối cùng cho MATLAB parfor cho Python (Scipy, Numpy).Parfor for Python

Có giải pháp tương tự như parfor không? Nếu không, sự phức tạp của việc tạo ra cái gì?

UPDATE: Đây là một số đang tính toán điển hình mà tôi cần phải đẩy nhanh tiến độ

import numpy as np 

N = 2000 
output = np.zeros([N,N]) 
for i in range(N): 
    for j in range(N): 
     output[i,j] = HeavyComputationThatIsThreadSafe(i,j) 

Một ví dụ về một hàm tính toán nặng là:

import scipy.optimize 

def HeavyComputationThatIsThreadSafe(i,j): 
    n = i * j 

    return scipy.optimize.anneal(lambda x: np.sum((x-np.arange(n)**2)), np.random.random((n,1)))[0][0,0] 

Trả lời

16

Có rất nhiều Python frameworks for parallel computing. Điều tôi thích nhất là IPython, nhưng tôi không biết nhiều về những người khác. Trong IPython, một điểm tương tự để parfor sẽ là client.MultiEngineClient.map() hoặc một số cấu trúc khác trong the documentation on quick and easy parallelism.

+1

+1 Không biết về khách hàng.MultiEngineClient mặc dù tôi sử dụng IPython. Cảm ơn các chỉ đạo! –

+0

Nó không phải là rõ ràng với tôi cho dù tôi có thể chạy một mã tăng tốc với khuôn khổ tính toán song song IPython trong chế độ kịch bản, tức là không chạy qua ipython. –

+0

@Dat Chu: Tất nhiên bạn có thể. Chỉ cần viết các lệnh bạn sẽ gõ vào dấu nhắc trong một tập tin chạy nó với Python. (Đây có phải là những gì bạn đang yêu cầu không?) –

3

Tôi luôn sử dụng Parallel Python nhưng nó không phải một tương tự hoàn chỉnh vì tôi tin rằng nó thường sử dụng các quy trình riêng biệt có thể tốn kém trên một số hệ điều hành nhất định. Tuy nhiên, nếu cơ thể của vòng của bạn là đủ chunky thì điều này sẽ không quan trọng và thực sự có thể có một số lợi ích.

25

Người được xây dựng trong trăn sẽ là multiprocessing tài liệu là here. Tôi luôn sử dụng multiprocessing.Pool với nhiều công nhân làm bộ vi xử lý. Sau đó, bất cứ khi nào tôi cần phải thực hiện cấu trúc giống như vòng lặp, tôi sử dụng Pool.imap

Miễn là phần thân của hàm của bạn không phụ thuộc vào bất kỳ lần lặp trước nào thì bạn nên có tốc độ tuyến tính gần. Điều này cũng yêu cầu đầu vào và đầu ra của bạn là pickle-nhưng điều này là khá dễ dàng để đảm bảo cho các loại tiêu chuẩn.

UPDATE: Một số mã cho chức năng cập nhật của bạn chỉ để hiển thị cách dễ dàng là:

from multiprocessing import Pool 
from itertools import product 

output = np.zeros((N,N)) 
pool = Pool() #defaults to number of available CPU's 
chunksize = 20 #this may take some guessing ... take a look at the docs to decide 
for ind, res in enumerate(pool.imap(Fun, product(xrange(N), xrange(N))), chunksize): 
    output.flat[ind] = res 
+0

Bạn nên thay thế 'output [ind]' bằng 'output.flat [ind]' để làm cho mã hoạt động. ('output' là mảng hai chiều và sẽ cần hai chỉ số.) –

+0

@Sven: Cảm ơn ... đến từ việc chuyển đổi giữa MATLAB và python mọi lúc. – JudoWill

2

Jupyter Notebook

Để xem một ví dụ xem xét bạn muốn viết sự tương đương của mã Matlab này trên trong Python

matlabpool open 4 
parfor n=0:9 
    for i=1:10000 
     for j=1:10000 
      s=j*i 
     end 
    end 
    n 
end 
disp('done') 

Cách có thể viết điều này trong python, đặc biệt là trong sổ ghi chép jupyter. Bạn phải tạo một hàm trong thư mục làm việc (tôi gọi nó FunForParFor.py) trong đó có những điều sau

def func(n): 
    for i in range(10000): 
     for j in range(10000): 
      s=j*i 
    print(n) 

Sau đó, tôi đi đến máy tính xách tay Jupyter của tôi và viết đoạn mã sau

import multiprocessing 
import FunForParFor 

if __name__ == '__main__': 
    pool = multiprocessing.Pool(processes=4) 
    pool.map(FunForParFor.func, range(10)) 
    pool.close() 
    pool.join() 
    print('done') 

này có đã làm cho tôi! Tôi chỉ muốn chia sẻ nó ở đây để cung cấp cho bạn một ví dụ cụ thể.