web-dev-qa-db-ja.com

PySparkの個別のスレッドから1つのSparkcontextで複数のジョブを実行するにはどうすればよいですか?

Sparkについてのドキュメント アプリケーション内でのスケジューリング

特定のSparkアプリケーション(SparkContextインスタンス)内で、複数の並列ジョブが別々のスレッドから送信された場合、それらを同時に実行できます。「ジョブ」とは、このセクションでは、Sparkアクション(例:保存、収集)およびそのアクションを評価するために実行する必要のあるタスク。Sparkのスケジューラは完全にスレッドセーフであり、このユースケースをサポートして、複数のリクエスト(例:複数のユーザーのクエリ)を提供するアプリケーションを有効にします。 」

ScalaとJavaで同じコードの例をいくつか見つけることができました。PySparkを使用してこれを実装する方法の例を誰かが示すことができますか?

19
Meethu Mathew

同じ問題が発生したため、小さな自己完結型の例を作成しました。 Pythonのスレッドモジュールを使用して複数のスレッドを作成し、複数のsparkジョブを同時に送信します。

デフォルトでは、sparkは先入れ先出し(FIFO)でジョブを実行します: http://spark.Apache.org/docs/latest/job- schedule.html#scheduling-within-an-application 。以下の例では、FAIRスケジューリングに変更します

# Prereqs:
# set 
# spark.dynamicAllocation.enabled         true
# spark.shuffle.service.enabled           true
  spark.scheduler.mode                    FAIR
# in spark-defaults.conf

import threading
from pyspark import SparkContext, SparkConf

def task(sc, i):
  print sc.parallelize(range(i*10000)).count()

def run_multiple_jobs():
  conf = SparkConf().setMaster('local[*]').setAppName('appname')
  # Set scheduler to FAIR: http://spark.Apache.org/docs/latest/job-scheduling.html#scheduling-within-an-application
  conf.set('spark.scheduler.mode', 'FAIR')
  sc = SparkContext(conf=conf)
  for i in range(4):
    t = threading.Thread(target=task, args=(sc, i))
    t.start()
    print 'spark task', i, 'has started'


run_multiple_jobs()

出力:

spark task 0 has started
spark task 1 has started
spark task 2 has started
spark task 3 has started
30000
0 
10000
20000
11
sparknoob

今日も同じことを聞いていました。マルチプロセッシングモジュールはThreadPoolを提供します。これはいくつかのスレッドを生成するため、ジョブを並列で実行します。最初に関数をインスタンス化し、次にプールを作成してから、反復したい範囲でそれをmapします。

私の場合、さまざまな中心数(ハイパーパラメーターチューニング)に対してこれらのWSSSE数を計算して、 MLSparkドキュメント 。これ以上の説明はありませんが、ここに私のIPythonワークシートのいくつかのセルがあります。

from pyspark.mllib.clustering import KMeans
import numpy as np

c_pointsは12dim配列です:

>>> c_points.cache()
>>> c_points.take(3)
[array([ 1, -1,  0,  1,  0,  0,  0,  0,  0,  0,  0,  0]),
array([-2,  0,  0,  1,  0,  0,  0,  0,  0,  0,  0,  0]),
array([ 7, -1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0])]

以下では、各iについて、このWSSSE値を計算してタプルとして返しています。

def error(point, clusters):
    center = clusters.centers[clusters.predict(point)]
    return np.linalg.norm(point - center)

def calc_wssse(i):
    clusters = KMeans.train(c_points, i, maxIterations=20,
        runs=20, initializationMode="random")
    WSSSE = c_points\
        .map(lambda point: error(point, clusters))\
        .reduce(lambda x, y: x + y)
    return (i, WSSSE)

ここから興味深い部分が始まります:

from multiprocessing.pool import ThreadPool
tpool = ThreadPool(processes=4)

それを実行します:

wssse_points = tpool.map(calc_wssse, range(1, 30))
wssse_points

与える:

[(1, 195318509740785.66),
 (2, 77539612257334.33),
 (3, 78254073754531.1),
 ...
]
3
Harald Schilly