如何定义一个好的分区计划以确保 JSR 352 中的 CPU 平衡?

How to define a good partition plan to ensure CPU balance in JSR 352?

JSR 352 - Java 平台的批处理应用程序 使用分区提供并行功能。批次运行时间可以分步执行一个步骤,以加快进度。 JSR 352 还引入了 threads 定义:我们可以定义要使用的线程数,例如

<step id="Step1">
    <chunk .../>
        <partition>
            <plan partitions="3" threads="2"/>
        </partition>
    </chunk>
</step>

然后我很困惑:如何给一个赞赏的分区计划,让每个线程都被占用并保证CPU平衡?

比如有table个A、B、C要做,他们的行数分别是10亿、100万、1000。该步骤旨在将这些实体处理为文档,一个实体转到一个文档。文档生成的顺序并不重要。这table个实体的CPU时间分别为1s、2s、5s。线程数为 4.

如果有 3 个分区,每个 table 类型一个,那么该步骤将需要 1 * 10^9 秒才能完成,因为:

但是,当线程 2 被占用时,线程 3 自 2 * 10^6s 起空闲,线程 4 自 5 * 10^3s 起空闲。所以很明显,这不是一个好的分区方案。

我的问题是:

答案...

Is there a better partition plan to complete in the above example?

是的,有。见答案 4...

Can I consider : partitions is a queue to consume and threads consume this queue ?

事情就是这样!

In general, how many threads can I / should I use ? Is that the same number of the CPU cores ?

视情况而定。这个问题有很多观点... 来自 JSR-352 规范视图, "threads":

Specifies the maximum number of threads on which to execute the partitions of this step. Note the batch runtime cannot guarantee the requested number of threads are available; it will use as many as it can up to the requested maximum. This is an optional attribute. The default is the number of partitions.

因此,仅基于这个角度,您应该将此值设置得尽可能高(批处理运行时将根据其资源设置实际限制!)。

从批处理运行时的角度(JSR352 实现):任何体面的实现都将使用线程池来执行分区步骤。所以,如果这样的池的大小固定为 N,那么无论你将线程数设置多大,你都不会同时执行超过 N 个分区。

JBeret 是 JSR352 规范的一个实现,供 wildfly 服务器使用(这是我用过的实现)。在 Wildfly,它的默认线程池设置为最多 10 个线程。这个池不仅在分区步骤之间共享,它也在批处理作业之间共享。因此,如果您同时 运行 2 个作业,您将少使用 2 个线程。除此之外,当你分区时,一个线程扮演协调者的角色,将分区分配给其他线程并等待结果......所以如果你的分区计划说它使用 2 个线程,它实际上会使用 3 个! (两个作为工作人员,一个作为协调员)......所有这些资源(线程)都来自同一个池!

无论如何,重要的是:调查您使用的是什么 JSR325 实现并相应地设置它

从硬件视图,您的CPU 有线程最大限制。在此观点下(根据经验),将 "threads" 值设置为该值。

从性能视图,分析您正在做的工作。如果您在多个线程之间访问共享资源(如数据库),则可能会产生导致线程阻塞的瓶颈。如果您遇到此类问题,您必须考虑降低 "theads" 值。

在摘要 中,将 "threads" 值设置为与 CPU 最大线程限制一样高。然后,检查该值是否不会导致阻塞问题;如果是,则降低该值。此外,验证批处理运行时是否已相应配置,并且它允许您执行任意数量的线程。

In general, how to give an appreciated partition plan so that each thread is occupied and ensure CPU balance ?

避免使用静态分区计划(至少对您而言)。相反,请使用分区映射器。分区映射器是一个 class,它实现了 javax.batch.api.partition.PartitionMapper 接口,并允许以编程方式定义分区计划(多少个分区、多少个线程、每个分区的属性)。因此,对于您的情况,将您的表(A、B、C)拆分为 N 个块(其中 N = 1000)……每个块将是一个分区。您应该从类型 C 的分区开始,并在您的实体分区(表)之间进行循环:C0B0A0B1A1 , ..., B999, A999, A1000, ..., A999999 ... 使用此方案,实体 C 将首先完成,留下一个线程打开解决更多的 A 和 B 分区。稍后,B 将完成,留下更多资源来攻击剩余的 A 分区。

希望这对您有所帮助...