我有一个Spark应用程序选择一个子集并对该子集执行一些操作。每个子集及其操作之间没有依赖关系和交互作用,因此我尝试使用多线程让它们并行运行以提高性能。代码如下:
Dataset<Row> fullData = sparkSession.read().json("some_path");
ExecutorService executor = Executors.newFixedThreadPool(10);
List<Runnable> tasks = Lists.newArrayList();
for (int i = 1; i <= 50; i++) {
final int x = i;
tasks.add(() -> {
Dataset<Row> subset_1 = fullData.filter(length(col("name")).equalTo(x));
Dataset<Row> subset_2 = fullData.filter(length(col("name")).equalTo(x));
Dataset<Row> result = subset_1.join(subset_2, ...);
log.info("Res size is " + result.count()); // force Spark do the join operation
});
}
CompletableFuture<?>[] futures = tasks.stream()
.map(task -> CompletableFuture.runAsync(task, executor))
.toArray(CompletableFuture[]::new);
CompletableFuture.allOf(futures).join();
executor.shutdown();
从Spark作业管理UI中,我注意到这50个任务是并行提交的,但是处理仍处于阻塞状态,一个任务开始运行,直到另一任务完成。如何使多个任务并行运行而不是一个接一个地运行?
答案 0 :(得分:1)
这不是您在Spark中控制并行性的方式。全部通过配置以声明方式控制。
Spark是一个分布式计算框架,旨在用于每个工作人员都运行单线程的分布式环境中。通常,使用具有节点元数据的Yarn计划任务,并且可能会在单个节点上启动多个任务(取决于内存和cpu约束),但在单独的jvm中。
在local
模式下,您可以将多个工作线程实现为单独的线程,因此,如果您说master("local[8]")
,则将在单个jvm中让8个工作线程作为线程运行。
您如何运行应用程序?