线程池(在驱动程序上)和执行程序内核之间的关系是什么?



我正在尝试使用 scala 的 Futures API 运行一个进程来并行运行某些操作。下面是一个示例代码片段

import scala.util._
import scala.concurrent._
import scala.concurrent.ExecutionContext.Implicits.global
object ConcurrentContext {
def def appMain(args: Array[String]) = {
// configure spark
val spark = SparkSession
.builder
.appName("parjobs")
.getOrCreate()
val pool = Executors.newFixedThreadPool(5)
// create the implicit ExecutionContext based on our thread pool
implicit val xc = ExecutionContext.fromExecutorService(pool)
/** Wraps a code block in a Future and returns the future */
def executeAsync[T](f: => T): Future[T] = {
Future(f)
}
} 

我的问题是:-

  1. 如果我将执行器核心值设置为 4,以控制每个执行器 JVM 的线程数,并在应用程序内创建一个 5 的线程池,哪个优先?

  2. 如果我没有显式设置线程池,则默认ExecutionContext将根据启动进程的计算机上存在的所有内核(这将是驱动程序)创建一个默认线程池,在这种情况下,执行器核心属性将如何影响?

  3. 如果线程池值优先于执行程序核心,并且如果我使用默认值,则每个 JVM 是否有可能有许多线程(等于 CPU 内核)?

如果我将执行器核心值设置为 4,它控制每个执行器 JVM 的线程数,并在应用程序内创建一个 5 的线程池

执行 Spark 应用程序时,您拥有驱动程序和一个或多个执行程序。为简单起见,假设您只有一个执行程序。

您有 4 个用于执行程序的 CPU。

您可以与 4 个 CPU 并行运行多少个任务?正好是 4 个!

驱动程序在具有 5 个线程池的 Spark 应用程序的该部分中运行。为了简单起见,我们假设使用了所有 5 个。

您可以安排多少个 Spark 作业?正好是 5 个!

每个 Spark 作业都可以有一个或多个阶段,其中包含一个或多个分区以使用任务进行处理。为了简单起见,让我们假设所有 5 个 Spark 作业都有 1 个阶段和 1 个分区(这不太可能,但只是为了让您了解 Spark 的工作原理,它应该没问题)。

请记住,1 个分区正好是 1 个任务。

Spark 应用程序将提交多少个任务?5 个作业,每个作业 1 个任务提供 5 个任务。

在 5-CPU 执行器上执行所有 5 个任务需要多少时间?1 个时隙(无论"时隙"可能意味着什么)。

这是执行程序核心/CPU 与驱动程序上 5 个线程的线程池之间的关系。

如果我没有显式设置线程池,那么默认的 ExecutionContext 将根据启动进程的计算机上存在的所有内核(这将是驱动程序)创建一个默认线程池,在这种情况下,执行器核心属性将如何影响?

我认为上面的部分也回答了这个问题。

如果线程池值优先于执行程序核心,并且如果我使用默认值,则每个 JVM 是否有可能有许多线程(等于 CPU 内核)?

它也是如此。正确?

最新更新