2014-09-10 21 views
11

Tôi có một tập lệnh python mà tôi đã viết bằng cách sử dụng mô-đun đa xử lý, để thực thi nhanh hơn. Việc tính toán là một cách lúng túng song song, do đó hiệu quả sẽ tăng lên với số lượng bộ vi xử lý. Bây giờ, tôi muốn sử dụng điều này trong một chương trình MPI, quản lý một phép tính MCMC trên nhiều máy tính. Mã này có một cuộc gọi đến hệ thống() mà gọi kịch bản python. Tuy nhiên, tôi thấy rằng khi nó được gọi là cách này, hiệu quả đạt được từ việc sử dụng đa xử lý python biến mất.Đa xử lý Python trong mpi

Làm cách nào để lấy tập lệnh python để giữ lại tốc độ tăng từ quá trình xử lý đa khi được gọi từ MPI?

Dưới đây là một ví dụ đơn giản, tương tự với các mã phức tạp hơn nhiều mà tôi muốn sử dụng nhưng hiển thị cùng một hành vi chung. Tôi viết một kịch bản python thực thi được gọi là junk.py.

#!/usr/bin/python 
import multiprocessing 
import numpy as np 

nproc = 3 
nlen = 100000 


def f(x): 
    print x 
    v = np.arange(nlen) 
    result = 0. 
    for i, y in enumerate(v): 
     result += (x+v[i:]).sum() 
    return result 


def foo(): 
    pool = multiprocessing.Pool(processes=nproc) 
    xlist = range(2,2+nproc) 
    print xlist 
    result = pool.map(f, xlist) 
    print result 

if __name__ == '__main__': 
    foo() 

Khi tôi tự chạy từ vỏ, sử dụng "trên cùng", tôi có thể thấy ba quy trình python mỗi 100% CPU trên máy 16 lõi của tôi.

node094:mpi[ 206 ] /usr/bin/time junk.py 
[2, 3, 4] 
2 
3 
4 
[333343333400000.0, 333348333450000.0, 333353333500000.0] 
62.68user 0.04system 0:21.11elapsed 297%CPU (0avgtext+0avgdata 16516maxresident)k 
0inputs+0outputs (0major+11092minor)pagefaults 0swaps 

Tuy nhiên, nếu tôi gọi điều này bằng mpirun, mỗi quá trình python chiếm 33% CPU và tổng thể mất khoảng ba lần để chạy. Gọi với -np 2 hoặc nhiều kết quả trong nhiều quy trình hơn, nhưng không tăng tốc độ tính toán bất kỳ.

node094:mpi[ 208 ] /usr/bin/time mpirun -np 1 junk.py 
[2, 3, 4] 
2 
3 
4 
[333343333400000.0, 333348333450000.0, 333353333500000.0] 
61.63user 0.07system 1:01.91elapsed 99%CPU (0avgtext+0avgdata 16520maxresident)k 
0inputs+8outputs (0major+13715minor)pagefaults 0swaps 

(Ghi chú thêm: Đây là mpirun 1.8.1, python 2.7.3 trên phiên bản Linux Debian khò khè hệ thống tôi đã nghe nói() không phải luôn luôn cho phép trong phạm vi chương trình MPI, nhưng nó đã làm việc cho tôi cho. Ví dụ, tôi đã gọi một mã song song dựa trên pthread từ system() trong một chương trình MPI, và nó được sử dụng 100% cpu cho mỗi luồng, như mong muốn. Ngoài ra, trong trường hợp bạn định đề xuất chạy kịch bản python trong serial và chỉ gọi nó trên nhiều nút hơn ... tính toán MCMC liên quan đến một số chuỗi cố định cần di chuyển theo cách được đồng bộ hóa, do đó tính toán không may không thể được tổ chức lại theo cách đó.)

Trả lời

8

OpenMPI's mpirun, v1.7 and later, mặc định để ràng buộc các quy trình để lõi - đó là, khi nó khởi chạy quá trình python junk.py, nó liên kết nó với lõi mà nó sẽ chạy trên đó. Đó là tốt, và hành vi mặc định đúng cho hầu hết các trường hợp sử dụng MPI. Nhưng ở đây, mỗi nhiệm vụ của MPI sau đó sẽ thúc đẩy nhiều quy trình hơn (thông qua gói đa xử lý), và những quy trình chia rẽ này thừa hưởng trạng thái ràng buộc của bố mẹ chúng - vì vậy chúng được gắn kết với cùng một lõi, chiến đấu với nhau. (Cột "P" ở trên cùng sẽ hiển thị tất cả chúng trên cùng một bộ xử lý)

Nếu bạn mpirun -np 2, bạn sẽ tìm thấy hai bộ ba quy trình, mỗi bộ trên một lõi khác nhau, mỗi chính họ.

Với OpenMPI, bạn có thể tránh điều này bằng cách tắt ràng buộc,

mpirun -np 1 --bind-to none junk.py 

hoặc chọn một số ràng buộc khác mà làm cho tinh thần được hình học cuối cùng của chạy của bạn. MPICH có similar options with hydra.

Lưu ý rằng fork() của các quy trình con với mpi isn't always safe or supported, đặc biệt là với các cụm đang chạy với các liên kết nội bộ, nhưng mpirun/mpiexec của OpenMPI sẽ cảnh báo bạn nếu nó không an toàn.

+0

để câu trả lời là tắt tính năng đa xử lý trong tập lệnh? – Cmag

+1

Xin lỗi, câu trả lời cho phần nào? Việc khởi chạy với --bind-to none sẽ tránh được sự cố CPU.Đối với vấn đề với fork, mpirun/mpiexec của OpenMPI sẽ cho bạn biết nếu bạn đang chạy trong các tình huống mà fork-ing không an toàn, và bạn có thể giải quyết vấn đề đó khi/nếu nó phát sinh. –

+0

Tôi đã xác nhận giải pháp này hoạt động, cả với ví dụ đơn giản và mã thực của tôi. Cảm ơn rất nhiều! Tôi đoán hành vi này của mpirun thay đổi cùng với các tùy chọn liên kết trong phiên bản 1.7 của openmpi, nếu không thì tôi không thể thấy tại sao một số mã tôi đã chạy trước đó sẽ hoạt động. –