Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 为什么每个Spark任务都没有使用所有分配的内核?_Scala_Performance_Apache Spark_Concurrency_Spark Dataframe - Fatal编程技术网

Scala 为什么每个Spark任务都没有使用所有分配的内核?

Scala 为什么每个Spark任务都没有使用所有分配的内核?,scala,performance,apache-spark,concurrency,spark-dataframe,Scala,Performance,Apache Spark,Concurrency,Spark Dataframe,假设每个执行器有36个核心,每个节点有一个执行器,3个节点有48个可用核心。我注意到的基本要点是,当我将每个任务设置为使用1个内核(默认值)时,我对workers的CPU利用率约为70%,每个执行器将同时执行36个任务(如我所料)。但是,当我将配置更改为每个任务有6个内核(--conf spark.task.cpus=6)时,每个执行器一次可以减少到6个任务(正如预期的那样),但是我的CPU利用率也会下降到10%以下(出乎意料)。我假设Spark知道如何在6核上并行化工作负载 重要的实现细节是,

假设每个执行器有36个核心,每个节点有一个执行器,3个节点有48个可用核心。我注意到的基本要点是,当我将每个任务设置为使用1个内核(默认值)时,我对workers的CPU利用率约为70%,每个执行器将同时执行36个任务(如我所料)。但是,当我将配置更改为每个任务有6个内核(
--conf spark.task.cpus=6
)时,每个执行器一次可以减少到6个任务(正如预期的那样),但是我的CPU利用率也会下降到10%以下(出乎意料)。我假设Spark知道如何在6核上并行化工作负载

重要的实现细节是,我在
DataFrame
的一列上运行一个UDF函数,并将结果作为新列附加到该DataFrame上。这个UDF函数使用一个
@transient
对象,它提供了我正在使用的机器学习算法。此UDF函数不是聚合或合并操作的一部分,它只是对列执行的
map
操作,如下所示:

def myUdf = udf { ... }

val resultSet = myUdf(dataFrame.col("originalCol"))
val dataFrameWithResults = dataFrame.withColumn("originalColMetric", resultSet)
我本以为Spark会执行6
myUdf
,一次处理6条记录,每个核心一条,但事实似乎并非如此。有没有办法解决这个问题(不向Spark项目提交PR),或者至少有人能解释为什么会发生这种情况


考虑到这个问题,我正在尝试增加每个任务的内核数量,以减少每个执行器所需的RAM数量。在本例中,一次执行太多任务会以指数方式增加RAM的使用量。

spark.task.cpu是为每个任务分配的多个内核。当用户代码为多线程时,它用于将多个内核分配给单个任务。如果您的
udf
没有使用多个线程(不会在一个函数调用中产生多个线程),那么内核就被浪费了

一次处理6条记录

分配6个内核,
spark.task.cpu
设置为1。如果要限制节点上的任务数,请减少每个节点提供的核心数


实际上,Spark可以通过在每个任务之间分割记录(根据分区)并确定每个执行者可以同时处理多少个任务,自行决定如何在多个记录上同时分割映射UDF。但是,Spark不能自动将每个核心的工作分配给每个任务。要在每个任务中使用多个核,需要编写UDF中的代码(每个任务一次(顺序)在一条记录上执行),以便在单个记录上并行该UDF中的计算。

另一个选项是转换为RDD并使用
mapPartitions
,然后将包含任务/分区项的集合转换为并行集合,并将转换映射到并行集合中的每个项。