2012-06-01 52 views
18

Tôi đã viết một thuật toán lấy dữ liệu không gian địa lý và thực hiện một số bước. Dữ liệu đầu vào là một shapefile của đa giác và raster covariate cho một khu vực nghiên cứu raster lớn (~ 150 triệu điểm ảnh). Các bước thực hiện như sau:Thiết kế đa xử lý Python

  1. điểm mẫu từ bên trong đa giác của shapefile
  2. Đối với mỗi điểm lấy mẫu, giá trị chiết xuất từ ​​rasters covariate
  3. Xây dựng một mô hình dự đoán trên các điểm lấy mẫu
  4. Extract đồng biến cho các điểm lưới mục tiêu
  5. Áp dụng mô hình dự đoán cho lưới mục tiêu
  6. Ghi dự đoán cho một tập hợp các lưới đầu ra

Toàn bộ quá trình cần được lặp lại nhiều lần (nói 100) nhưng mỗi lần lặp lại hiện mất hơn một giờ khi được xử lý theo chuỗi. Đối với mỗi lần lặp lại, phần tốn nhiều thời gian nhất là bước 4 và 5. Vì lưới mục tiêu quá lớn nên tôi đã xử lý nó một khối (nói 1000 hàng) tại một thời điểm.

Tôi có CPU 6 lõi với RAM 32 Gb, vì vậy trong mỗi lần lặp lại, tôi đã sử dụng mô-đun multiprocessing của Python với đối tượng Pool để xử lý đồng thời một số khối (bước 4 và 5) và sau đó viết đầu ra (các dự đoán) cho tập hợp chung của các lưới đầu ra bằng cách sử dụng một hàm gọi lại gọi một hàm đầu ra toàn cầu. Điều này dường như hoạt động, nhưng không nhanh hơn (thực sự, nó có thể chậm hơn) so với xử lý từng khối trong chuỗi.

Vì vậy, câu hỏi của tôi là, có cách nào hiệu quả hơn để làm điều đó không? Tôi quan tâm đến lớp học đa năng của mô-đun đa xử lý là Queue, nhưng tôi không thực sự chắc chắn nó hoạt động như thế nào. Ví dụ, tôi tự hỏi nếu nó có hiệu quả hơn để có một hàng đợi thực hiện các bước 4 và 5 sau đó vượt qua các kết quả đến một hàng đợi khác mà thực hiện bước 6. Hoặc là điều này ngay cả những gì Queue là?

Mọi con trỏ sẽ được đánh giá cao.

+0

RSS tối đa trong toàn bộ quá trình là gì? Có lẽ nó sẽ được dễ dàng hơn để chỉ cần chạy điều này sáu lần đồng thời nếu nó sẽ tất cả phù hợp với bộ nhớ ... – sarnold

+0

Bạn có thực sự CPU bị ràng buộc? Điều này trông giống như một vấn đề ràng buộc I/O. – stark

+0

@ Sarnold: Nó sẽ không hoàn toàn phù hợp với trí nhớ, đó là vấn đề ... – hendra

Trả lời

3

Trạng thái hiện tại của khả năng đa xử lý của Python là không tuyệt vời cho CPU bound Chế biến. Tôi sợ phải nói với bạn rằng không có cách nào để làm cho nó chạy nhanh hơn bằng cách sử dụng mô-đun multiprocessing cũng không phải là việc bạn sử dụng multiprocessing đó là vấn đề.

Vấn đề thực sự là Python vẫn bị ràng buộc bởi các quy tắc của GlobalInterpreterLock(GIL) (Tôi rất gợi ý số slides). Đã có một số lý thuyết thú vị và experimental advances về làm việc xung quanh GIL. Sự kiện Python 3.2 chứa một GIL mới giải quyết một số vấn đề, nhưng giới thiệu những vấn đề khác.

Hiện tại, thực hiện nhanh hơn nhiều quy trình Python với một chuỗi nối tiếp đơn lẻ hơn là cố chạy nhiều luồng trong một quy trình. Điều này sẽ cho phép bạn tránh các vấn đề có được GIL giữa các luồng (bằng cách hiệu quả có nhiều GIL hơn). Tuy nhiên, điều này chỉ mang lại lợi ích nếu chi phí IPC giữa các quá trình Python của bạn không làm lu mờ lợi ích của quá trình xử lý.

Eli Bendersky đã viết một phong nha overview article về kinh nghiệm của mình với nỗ lực để làm cho một quá trình ràng buộc CPU chạy nhanh hơn với đa xử lý.

Cần lưu ý rằng PEP 371 có mong muốn 'bước bên' GIL với sự ra đời của mô-đun multiprocessing (trước đây là gói không chuẩn được đặt tên pyProcessing). Tuy nhiên GIL vẫn có vẻ đóng vai trò quá lớn trong trình thông dịch Python để làm cho nó hoạt động tốt với các thuật toán liên kết CPU. Nhiều người khác nhau đã làm việc để loại bỏ/viết lại GIL, nhưng không có gì có đủ lực kéo để biến nó thành một bản phát hành Python.

+0

Tôi nghi ngờ rằng đây là trường hợp. Tôi chắc chắn sẽ kiểm tra các liên kết của bạn, cảm ơn. Trên một tack hơi khác nhau: Tôi đoán sau đó mô-đun song song Python sẽ phải chịu cùng một loại vấn đề. Nhưng nếu, nói, PP được sử dụng để phân chia nhiệm vụ giữa nhiều máy tính? – hendra

+0

@npo bất kỳ cập nhật nào? –

+0

Xin lỗi, chưa! – hendra

0

Tôi khuyên bạn trước tiên hãy kiểm tra xem các mã nào của bạn đang sử dụng nhiều nhất, vì vậy bạn phải lập hồ sơ, tôi đã sử dụng http://packages.python.org/line_profiler/#line-profiler với nhiều thành công, mặc dù nó yêu cầu cython.

Đối với Hàng đợi, chủ yếu được sử dụng để chia sẻ luồng dữ liệu/đồng bộ hóa, mặc dù tôi hiếm khi sử dụng nó. Tôi sử dụng đa xử lý mọi lúc.

Tôi chủ yếu làm theo bản đồ giảm triết học, đó là đơn giản và sạch sẽ nhưng nó có một số chi phí lớn, vì giá trị phải được đóng gói vào từ điển và sao chép trên mỗi quá trình, khi áp dụng các chức năng bản đồ ...

Bạn có thể thử phân đoạn tệp của mình và áp dụng thuật toán cho các tập hợp khác nhau.

1

Một số ví dụ về đa xử lý tại python.org không phải là IMO rất rõ ràng và rất dễ bắt đầu với thiết kế thiếu sót. Dưới đây là một ví dụ đơn giản mà tôi đã thực hiện để giúp tôi bắt đầu dự án:

import os, time, random, multiprocessing 
def busyfunc(runseconds): 
    starttime = int(time.clock()) 
    while 1: 
     for randcount in range(0,100): 
      testnum = random.randint(1, 10000000) 
      newnum = testnum/3.256 
     newtime = int(time.clock()) 
     if newtime - starttime > runseconds: 
      return 

def main(arg): 
    print 'arg from init:', arg 
    print "I am " + multiprocessing.current_process().name 

    busyfunc(15) 

if __name__ == '__main__': 

    p = multiprocessing.Process(name = "One", target=main, args=('passed_arg1',)) 
    p.start() 

    p = multiprocessing.Process(name = "Two", target=main, args=('passed_arg2',)) 
    p.start() 

    p = multiprocessing.Process(name = "Three", target=main, args=('passed_arg3',)) 
    p.start() 

    time.sleep(5) 

Điều này nên thực hiện 3 bộ xử lý trong 15 giây. Nó sẽ được dễ dàng để sửa đổi nó để biết thêm. Có lẽ điều này sẽ giúp gỡ lỗi mã hiện tại của bạn và đảm bảo bạn đang thực sự tạo ra nhiều quy trình độc lập.

Nếu bạn phải chia sẻ dữ liệu do RAM hạn chế, sau đó tôi đề nghị này: http://docs.python.org/library/multiprocessing.html#sharing-state-between-processes

1

Như python là không thực sự có nghĩa là để làm sâu số-cunching, tôi thường bắt đầu chuyển đổi phần thời gian quan trọng của một chương trình python để C/C++ và tăng tốc độ lên rất nhiều.

Ngoài ra, đa luồng trăn không phải là rất tốt. Python tiếp tục sử dụng một semaphore toàn cầu cho tất cả mọi thứ. Vì vậy, ngay cả khi bạn sử dụng các chủ đề mà python cung cấp, mọi thứ sẽ không nhanh hơn. Các chủ đề rất hữu ích cho các ứng dụng, nơi mà các chủ đề thường sẽ chờ đợi những thứ như IO.

Khi tạo mô-đun C, bạn có thể tự giải phóng toàn bộ semaphore khi xử lý dữ liệu của bạn (sau đó, tất nhiên, không truy cập vào giá trị python nữa).

Cần thực hành một số cách sử dụng API C, nhưng nó được cấu trúc rõ ràng và dễ sử dụng hơn, ví dụ, API gốc Java.

Xem 'mở rộng và nhúng' trong tài liệu python.

Bằng cách này bạn có thể làm cho thời gian bộ phận quan trọng trong C/C++, và các bộ phận chậm hơn với công việc lập trình nhanh hơn trong python ...

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