![](/img/trans.png)
[英]How to run multiple shell jobs using separate threads and wait for each to finish after executing each simultaneously?
[英]How to run multiple jobs in one Sparkcontext from separate threads in PySpark?
从 Spark documentation about Scheduling Within an Application中了解到:
在给定的 Spark 应用程序(SparkContext 实例)中,如果多个并行作业是从不同的线程提交的,则它们可以同时运行。 在本节中,“作业”是指 Spark 操作(例如保存、收集)以及需要运行以评估该操作的任何任务。 Spark 的调度程序是完全线程安全的,并支持此用例以启用服务于多个请求的应用程序(例如,多个用户的查询)。”
我可以在 Scala 和 Java 中找到一些相同的示例代码。 有人可以举例说明如何使用 PySpark 实现这一点吗?
我遇到了同样的问题,所以我创建了一个独立的小例子。 我使用 python 的线程模块创建多个线程并同时提交多个火花作业。
请注意,默认情况下,spark 将以先进先出 (FIFO) 的方式运行作业:http: //spark.apache.org/docs/latest/job-scheduling.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
今天,我也在问我同样的问题。 multiprocessing 模块提供了一个ThreadPool
,它为您生成了几个线程,因此并行运行作业。 首先实例化函数,然后创建池,然后将其map
到要迭代的范围内。
就我而言,我正在为不同数量的中心(超参数调整)计算这些 WSSSE 数字,以获得“良好的”k-means 聚类……就像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),
...
]
ThreadPool
很方便,但可能会导致意外行为。 例如,如果所有线程都使用overwrite
模式将数据帧写入同一位置,那么线程是否“覆盖”彼此的文件取决于时间。 这很像“先到先得”。
通常所有线程都会同时被评估/实现,所以这个位置最终会包含来自所有线程的所有文件(就好像它们都处于append
模式一样)。 但是如果某些线程有延迟,它们当然可以覆盖其他线程的文件。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.