web-dev-qa-db-ja.com

大Pandasデータフレーム並列処理

非常に大きなPandasデータフレームにグローバル変数としてアクセスしています。この変数は joblib を介して並行してアクセスされます。

例えば。

df = db.query("select id, a_lot_of_data from table")

def process(id):
    temp_df = df.loc[id]
    temp_df.apply(another_function)

Parallel(n_jobs=8)(delayed(process)(id) for id in df['id'].to_list())

この方法で元のdfにアクセスすると、プロセス間でデータがコピーされるようです。元のdfはどのサブプロセスでも変更されていないため、これは予期しないことですか? (またはそれは?)

11
autodidacticon

Joblibによって作成されたプロセスごとに、DataFrame全体をピクル化およびピクルス解除する必要があります。実際には、これは非常に遅く、それぞれのメモリの何倍も必要です。

1つの解決策は、テーブル形式を使用してデータをHDF(df.to_hdf)に保存することです。次に、selectを使用して、さらに処理するデータのサブセットを選択できます。実際には、これはインタラクティブに使用するには遅すぎます。また、非常に複雑であり、最終ステップで統合できるように、作業者は作業を保存する必要があります。

別の方法は、numba.vectorizetarget='parallel'で探索することです。これには、Pandasオブジェクトではなく、NumPy配列を使用する必要があるため、複雑さのコストもかかります。

長期的には、 dask がパンダに並列実行をもたらすことが期待されていますが、これはすぐには期待できません。

12
Kevin S

前述のように、Pythonマルチプロセッシングは通常、個別のプロセスを使用して実行されます。つまり、プロセスはメモリを共有しません。 joblibドキュメントの少し下で述べたように、np.memmapで動作させることができれば、潜在的な回避策がありますが、ディスクにダンプすると、明らかにそれ自体のオーバーヘッドが追加されます: https:// pythonhosted。 org/joblib/parallel.html#working-with-numerical-data-in-shared-memory-memmaping

3
Randy