2017-08-07 63 views
6

Ağustos 2017 itibariyle, Pandalar DataFame.apply() maalesef hala tek bir çekirdek ile çalışmakla sınırlı kalıyor, yani çok çekirdekli bir makinenin, df.apply(myfunc, axis=1)'u çalıştırdığınızda hesaplama zamanının çoğunu boşa harcayacağı anlamına geliyor.Pandas DataFrame'lerde, bir makinedeki tüm çekirdekleri kullanan apply() yöntemini nasıl paralelleştiriyorsunuz?

Paralel olarak bir veri çerçevesinde uygulamak için tüm çekirdeklerinizi nasıl kullanabilirsiniz?

cevap

7

En basit yol Dask's map_partitions kullanmaktır.

import pandas as pd 
import dask.dataframe as dd 
from dask.multiprocessing import get 

ve sözdizimi

data = <your_pandas_dataframe> 
ddata = dd.from_pandas(data, npartitions=30) 

def myfunc(x,y,z, ...): return <whatever> 

res = ddata.map_partitions(lambda df: df.apply((lambda row: myfunc(*row)), axis=1)).compute(get=get) 

(Sana 16 çekirdek varsa 30 bölümleri uygun sayıda olduğuna inanıyoruz) 'dir: (siz pip install dask gerekir) bu ithalat gerekir.

data = pd.DataFrame() 
data['col1'] = np.random.normal(size = 1500000) 
data['col2'] = np.random.normal(size = 1500000) 

ddata = dd.from_pandas(data, npartitions=30) 
def myfunc(x,y): return y*(x**2+1) 
def apply_myfunc_to_DF(df): return df.apply((lambda row: myfunc(*row)), axis=1) 
def pandas_apply(): return apply_myfunc_to_DF(data) 
def dask_apply(): return ddata.map_partitions(apply_myfunc_to_DF).compute(get=get) 
def vectorized(): return myfunc(data['col1'], data['col2'] ) 

t_pds = timeit.Timer(lambda: pandas_apply()) 
print(t_pds.timeit(number=1)) 

28,16970546543598

t_dsk = timeit.Timer(lambda: dask_apply()) 
print(t_dsk.timeit(number=1)) 

2,708152851089835

t_vec = timeit.Timer(lambda: vectorized()) 
print(t_vec.timeit(number=1)) 
: Sadece şeyiyle benim makinede farkı (16 çekirdek) zaman aşımına Bir faktör pandalar giden hızlanma 10 verilmesi

0,010668013244867325

bölümleri üzerinde uygulamak DASK için geçerlidir. Tabii ki, eğer bir fonksiyonunuz varsa, eğer bu durumda - eğer bu durumda fonksiyon (y*(x**2+1)) üç boyutlu olarak vektörel hale getirilmeli, ama vektörün imkansız hale getirilmesi imkansız olan birçok şey vardır.

+2

Bilmekte fayda var, yayın için teşekkürler. Neden 30 bölüm seçtiğini açıklayabilir misin? Bu değeri değiştirirken performans değişir mi? –

+0

@AndrewL Her bölüme ayrı bir işlem tarafından verildiğini ve 16 çekirdek ile 16 veya 32 işlemin aynı anda çalışabileceğini varsayalım. Denedim ve performans 32 bölüme kadar çıktı gibi görünüyor, ancak daha fazla artışlar hiçbir yararlı etkiye sahip değil. Dört çekirdekli bir makine ile 8 bölüm vb. Olmasını isterim. 16 ve 32 arasında bir gelişme olduğunu fark ettiğime göre, sanırım gerçekten 2x $ NUM_PROCESSORS istiyorsun. –