Python 如何从PySpark中的不同线程在一个Sparkcontext中运行多个作业?

Python 如何从PySpark中的不同线程在一个Sparkcontext中运行多个作业?,python,multithreading,apache-spark,pyspark,Python,Multithreading,Apache Spark,Pyspark,从Spark文档中可以了解到: 在给定的Spark应用程序(SparkContext实例)中,如果多个并行作业是从单独的线程提交的,则它们可以同时运行。在本节中,我们所说的“作业”是指Spark操作(例如保存、收集)以及需要运行以评估该操作的任何任务。Spark的调度程序是完全线程安全的,并支持此用例以启用服务于多个请求(例如,多个用户的查询)的应用程序。” 我在Scala和Java中几乎找不到类似的示例代码。 有人能举例说明如何使用PySpark实现这一点吗?今天,我也在问同样的问题。多处理模

从Spark文档中可以了解到:

在给定的Spark应用程序(SparkContext实例)中,如果多个并行作业是从单独的线程提交的,则它们可以同时运行。在本节中,我们所说的“作业”是指Spark操作(例如保存、收集)以及需要运行以评估该操作的任何任务。Spark的调度程序是完全线程安全的,并支持此用例以启用服务于多个请求(例如,多个用户的查询)的应用程序。”

我在Scala和Java中几乎找不到类似的示例代码。
有人能举例说明如何使用PySpark实现这一点吗?

今天,我也在问同样的问题。多处理模块提供了一个
线程池
,它为您生成了一些线程,因此并行运行作业。首先实例化函数,然后创建池,然后在整个范围内映射它e您想要迭代

在我的例子中,我计算了不同中心数(超参数调整)的WSSSE数,以获得“良好”的k-均值聚类…正如中所述。在没有进一步解释的情况下,以下是我的IPython工作表中的一些单元格:

from pyspark.mllib.clustering import KMeans
import numpy as np
c_点为12维阵列:

>>> 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
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),
 ...
]

我遇到了同样的问题,所以我创建了一个小型的自包含示例。我使用python的线程模块创建多个线程,并同时提交多个spark作业

请注意,默认情况下,spark将在先进先出(FIFO)中运行作业

# 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

这里有没有得到答案?我也在尝试做同样的事情,并且认为在
SparkContext
s.@MikeSukmanowsky你是什么意思?这篇文档没有提到特定的Spark API,它似乎对所有API都有效。使用任何API时运行的实际代码是Scala代码,以及一些Java和Python的接口代码。你能提供这个语句来自何处的链接吗?…出于好奇,我通过
%timeit
对它进行了基准测试。串行执行(带有“脉动”行为)耗时53.2秒,而使用4个线程的并行化方法在16.2秒内完成。因此,这是一个真正的区别。更多的活动阶段是并行的,并且总是在队列中。这难道不会增加竞争条件的可能性吗?这可能取决于您使用的数据。由于您管理线程,您必须确保至少你自己不提高比赛条件。@HaraldSchilly你不必做
tpool.close()
tpool.join()
?你认为这是最好的方法吗?特别是当你在集群上时。由于sc保留在主节点上,而主节点将其分布在工作节点上,我在想这是否是最好的方法。关于使用线程库,有一些很好的说明,特别是对于返回线程计算机的结果这样的操作不公平。