2012-05-07 22 views
8

İki çok daha karmaşık Python betiği kullanan basit bir Python betiğine sahibim ve sonuçlarla bir şeyler yapıyor.Python'da çok basit eşzamanlı programlama

İki modül, Foo ve Bar, ve benim kod gibidir aşağıdadır:

import Foo 
import Bar 

output = [] 

a = Foo.get_something() 
b = Bar.get_something_else() 

output.append(a) 
output.append(b) 

Her iki yöntem çalışması uzun zaman alır ve ne diğer bağlıdır, bu yüzden bariz çözüm için Paralel olarak çalıştırın. Bunu nasıl sağlayabilirim, ancak siparişin devam ettiğinden emin olun: İlk önce hangisi bitiyorsa, komut dosyasının devam edebilmesi için diğerinin bitmesini beklemelisiniz. Kendimi yeterince açıklamamış olsaydım, örnek kodu mümkün olduğunca basitleştirmeye çalıştım.

DÜZENLEME:

Teşekkür Amber, çözüm tek ufak bir değişiklik ile çalışır. Ben eşzamanlılık hatayı AttributeError: 'NoneType' object has no attribute 'join' ve bazı çok garip davranış başlamıştı Bu olmadan

threadname = threading.Thread(target=foo) 
threadname.start() 

: Bunun yerine oluşturulduğunda her iş parçacığı üzerinde start() çağıran

, çok gibi onları kurmak . Cevabınızı aşağıda düzenlerseniz, bunu çözülmüş olarak işaretlerim.

cevap

20

Genel olarak bunu yapmak için threading kullanırsınız.

İlk olarak, paralel çalıştırmak istediğiniz her şey için bir iş parçacığı oluşturmak: bitirdikten için

import threading 

import Foo 
import Bar 

results = {} 

def get_a(): 
    results['a'] = Foo.get_something() 
a_thread = threading.Thread(target=get_a) 
a_thread.start() 

def get_b(): 
    results['b'] = Bar.get_something_else() 
b_thread = threading.Thread(target=get_b) 
b_thread.start() 

Sonra ikisi de gerektirecek şekilde, hem .join() kullanın:

a_thread.join() 
b_thread.join() 

hangi

output = [results['a'], results['b']] 
: Eğer sıralı bir listesini isteseydi böylece sonuçları, results['a'] ve results['b'] olacaktır işaret

Not: - multiprocessing çekirdeklerini ayırmak için görevleri dağıtabilir oysa Python'un GIL için, belirli bir Python işlemi sadece hiç bir işlemci çekirdeğini kullanacak nedeniyle her iki görevler doğal olarak ise CPU kullanımı yoğun, bunun yerine multiprocessing düşünebilirsiniz . Bununla birlikte, threading'dan biraz daha yüksek bir yüke sahiptir ve bu nedenle görevler daha az CPU yoğunsa, verimli olmayabilir.

+3

İş parçacığı, boşta olan kod için kullanışlıdır. Çok fazla ağır bir hesaplamaya sahipse, çok işlem yapılmasını tavsiye etmelisiniz çünkü iş parçacığı yalnızca bu durumda gecikme ekleyecektir. – akaRem

+0

@akaRem Elbette, bununla ilgili bir notta düzenleme yapabilirim. – Amber

+0

Evet, çok yoğun bir işlemci. İlk önce bu çalışmayı alacağım; Hızlı bir görünüm aldım ve API'ler aynı. – Rory

7
import multiprocessing 

import Foo 
import Bar 

results = {} 

def get_a(): 
    results['a'] = Foo.get_something() 



def get_b(): 
    results['b'] = Bar.get_something_else() 

process_a = multiprocessing.Process(target=get_a) 
process_b = multiprocessing.Process(target=get_b) 


process_b.start() 
process_a.start() 


process_a.join 
process_b.join 

Programınızın işlem sürümü aşağıdadır.

NOT: iş parçacığında paylaşılan veri yapıları vardır, bu nedenle kilitleme konusunda endişelenmeniz gerekir, bu da verilerin yanlış bir şekilde işlenmesini engeller ve ayrıca yukarıda bahsedilen kehribar gibi bir GIL (Global yorumlayıcı Kilitleme) sorunu içerir ve her iki göreviniz de CPU'dur Bu yoğunlaşmanın anlamı, iplik alma ve bırakma ipliklerini bildiren çağrılar nedeniyle daha fazla zaman alacağı anlamına gelir. Ancak, görevleriniz I/O yoğunsa, o zaman o kadar fazla etki yapmaz.

Artık bir işlemde paylaşılan veri yapıları olmadığından LOCKS hakkında endişelenmeyin ve GIL'den bağımsız olarak çalıştığı için çok işlemcilerin gerçek gücünü gerçekten seviyorsunuz.

Basit not hatırlamak: süreç parçacığı aynıdır sadece paylaşılan veriyapılarıdır kullanmadan (her şey tek başına çalışır ve mesajlaşma odaklanmıştır.)

çek dabeaz.com keresinde eşzamanlı programlama iyi bir sunum yaptı.