2014-10-16 17 views
5

Tôi đang cố gắng tối ưu hóa mã của mình bằng mô-đun multiprocessing.Pool của Python, nhưng tôi không nhận được kết quả tăng tốc mà tôi mong đợi một cách hợp lý.Khả năng đa xử lý Python không cho hiệu suất tăng tốc dự kiến ​​

Phương pháp chính mà tôi đang thực hiện liên quan đến việc tính toán các sản phẩm ma trận-vector cho một số lượng lớn vectơ và ma trận thưa thớt lớn cố định. Dưới đây là một ví dụ đồ chơi thực hiện những gì tôi cần, nhưng với ma trận ngẫu nhiên.

import time 
import numpy as np 
import scipy.sparse as sp 

def calculate(vector, matrix = None): 
    for i in range(50): 
     v = matrix.dot(vector) 
    return v 

if __name__ == '__main__': 
    N = 1e6 
    matrix = sp.rand(N, N, density = 1e-5, format = 'csr') 
    t = time.time() 
    res = [] 
    for i in range(10): 
     res.append(calculate(np.random.rand(N), matrix = matrix))  
    print time.time() - t 

Phương pháp chấm dứt trong khoảng 30 giây.

Bây giờ, vì việc tính toán từng phần tử results không phụ thuộc vào kết quả của bất kỳ phép tính nào khác, nên việc tính toán song song sẽ làm tăng tốc quá trình. Ý tưởng là tạo ra 4 quy trình và nếu mỗi phép tính thực hiện một số phép tính, thì thời gian cần cho tất cả các quy trình để hoàn thành sẽ giảm theo một số yếu tố xung quanh 4. Để làm điều này, tôi đã viết đoạn mã sau:

import time 
import numpy as np 
import scipy.sparse as sp 
from multiprocessing import Pool 
from functools import partial 

def calculate(vector, matrix = None): 
    for i in range(50): 
     v = matrix.dot(vector) 
    return v 

if __name__ == '__main__': 
    N = 1e6 
    matrix = sp.rand(N, N, density = 1e-5, format = 'csr') 

    t = time.time() 
    input = [] 
    for i in range(10): 
     input.append(np.random.rand(N)) 
    mp = partial(calculate, matrix = matrix) 
    p = Pool(4) 
    res = p.map(mp, input) 
    print time.time() - t 

Vấn đề của tôi là mã này có cao hơn một chút 20 giây để chạy, vì vậy tôi thậm chí không cải thiện hiệu suất của hệ số 2! Thậm chí tệ hơn, hiệu suất không không phải là cải thiện ngay cả khi hồ bơi chứa các quy trình 8! Bất kỳ ý tưởng tại sao tốc độ không xảy ra?


Note: Phương pháp thực tế của tôi mất nhiều thời gian, và các vectơ đầu vào được lưu trữ trong một tập tin. Nếu tôi chia tập tin trong 4 miếng và sau đó chạy kịch bản của tôi trong một quá trình riêng biệt cho mỗi tệp theo cách thủ công, mỗi quá trình chấm dứt bốn lần nhanh như nó sẽ cho toàn bộ tệp (như mong đợi). Tôi confuzed tại sao điều này tốc độ lên (mà rõ ràng là có thể) không xảy ra với multiprocessing.Pool


Edi: Tôi vừa tìm thấy Multiprocessing.Pool makes Numpy matrix multiplication slower câu hỏi này có thể liên quan. Tôi phải kiểm tra, mặc dù.

+0

Câu hỏi: Có bao nhiêu lõi CPU vật lý (không hyperthreaded) hệ thống bạn đang chạy trên có? –

+0

@KlausD. Về thể chất, tôi có lõi '4'. Đó là lý do tại sao tôi chia thủ công tệp thành '4', không phải là các phần' 8'. – 5xum

+0

Nếu bạn đặt một số điểm chuẩn 'time.time()' bên trong phương thức 'tính toán', bạn sẽ thấy các cuộc gọi 50' chấm' mất gần 4 lần so với các trường hợp không song song. Nó không rõ ràng với tôi tại sao bởi vì các công cụ như 'top' làm cho nó không phải là trường hợp song song chỉ sử dụng một CPU đầy đủ, trong khi trường hợp song song làm cho nó trông giống như 4 CPU đang được sử dụng đầy đủ. –

Trả lời

0

Hãy thử:

p = Pool(4) 
for i in range(10): 
    input = np.random.rand(N) 
    p.apply_async(calculate, args=(input, matrix)) # perform function calculate as new process with arguments input and matrix 

p.close() 
p.join() # wait for all processes to complete 

tôi nghi ngờ rằng đối tượng "một phần" và bản đồ được kết quả là một hành vi chặn. (Mặc dù tôi chưa bao giờ sử dụng một phần, vì vậy tôi không quen thuộc với nó.)

"apply_async" (hoặc "map_async") đều được đa xử phương pháp mà cụ thể không chặn - (xem: Python multiprocessing.Pool: when to use apply, apply_async or map?)

chung , đối với "các vấn đề song song xấu hổ" như thế này, apply_async làm việc cho tôi.

EDIT:

tôi có xu hướng để viết kết quả vào cơ sở dữ liệu MySQL khi tôi đang làm - thi tôi cung cấp không hoạt động nếu đó không phải là cách tiếp cận của bạn. "Bản đồ" có lẽ là câu trả lời đúng nếu bạn muốn sử dụng thứ tự trong danh sách như cách bạn theo dõi mục nhập nào, nhưng tôi vẫn còn nghi ngờ về các đối tượng "một phần".

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