web-dev-qa-db-ja.com

Sparkによるマルチプロセッシング(PySpark)

ユースケースは次のとおりです。

'user_id'列を含む大きなデータフレームがあります(すべてのuser_idは多くの行に表示される可能性があります)。ユーザーのリストがあります my_users 分析する必要があります。

Groupbyfilteraggregateは良い考えかもしれませんが、pysparkに含まれている利用可能な集計関数は私のニーズに合いませんでした。 pyspark verでは、ユーザー定義の集計関数はまだ完全にはサポートされていないため、今はそのままにしておくことにしました。

代わりに、 my_users リストを繰り返し、データフレーム内の各ユーザーをフィルタリングして分析します。この手順を最適化するために、 my_users の各ユーザーに対してpython multiprocessing poolを使用することにしました。

分析を行う(そしてプールに渡される)関数は、2つの引数を取ります:ser_idメインデータフレームへのパスで、すべての計算を実行します( [〜#〜] parquet [〜#〜]形式)。このメソッドでは、データフレームをロードして作業します(DataFrameを引数として渡すことはできません)

一部のプロセス(実行ごとに異なります)で、次のようなあらゆる種類の奇妙なエラーが発生します。

  • PythonUtilsはJVMに存在しません(「寄木細工の床」データフレームを読み取る場合)

print screen of the error message

  • KeyError: 'c' not found(また、 'parquet'データフレームを読み取る場合。とにかく 'c'とは??)

マルチプロセッシングなしで実行すると、すべてがスムーズに実行されますが、遅くなります。

これらのエラーがどこから来ているのか考えはありますか?

わかりやすくするために、コードサンプルをいくつか配置します。

PYSPRAK_SUBMIT_ARGS = '--driver-memory 4g --conf spark.driver.maxResultSize=3g --master local[*] pyspark-Shell' #if it's relevant

# ....

def users_worker(df_path, user_id):
    df = spark.read.parquet(df_path) # The problem is here!
    ## the analysis of user_id in df is here

def user_worker_wrapper(args):
    users_worker(*args)

def analyse():
    # ...
    users_worker_args = [(df_path, user_id) for user_id in my_users]
    users_pool = Pool(processes=len(my_users))
    users_pool.map(users_worker_wrapper, users_worker_args)
    users_pool.close()
    users_pool.join()
8
Mike

実際、@ user6910411がコメントしたように、プールをthreadPool(multiprocessing.pool.ThreadPoolパッケージ)に変更すると、すべてが期待どおりに機能し、これらのエラーはなくなりました。

エラー自体の根本的な理由も明らかになりました。共有したい場合は、以下にコメントしてください。

7
Mike