5

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

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

然后我就疑惑了:如何给出一个赞赏的分区方案,让每个线程都被占用,保证CPU的平衡?

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

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

  • 分区 A将占用1 * 10^9 * 1s = 1 * 10^9s,在线程 2 上运行
  • 分区 B将占用1 * 10^6 * 2s = 2 * 10^6s,在线程 3 上运行
  • 分区 C将占用1 * 10^3 * 5s = 5 * 10^3s,在线程 4 上运行

然而,当线程 2 被占用时,线程 3 是空闲的2 * 10^6s,线程 4 是空闲的5 * 10^3s。所以很明显,这不是一个好的分区计划。

我的问题是:

  • 在上面的例子中是否有更好的分区计划来完成?
  • 我可以考虑:分区是一个消费队列,线程消费这个队列吗?
  • 一般来说,我可以/应该使用多少个线程?CPU核心数是一样的吗?
  • 一般来说,如何给出一个赞赏的分区计划,让每个线程都被占用并保证CPU的平衡?
4

1 回答 1

3

答案...

在上面的例子中是否有更好的分区计划来完成?

就在这里。见答案4...

我可以考虑:分区是一个消费队列,线程消费这个队列吗?

这正是发生的事情!

一般来说,我可以/应该使用多少个线程?CPU核心数是一样的吗?

这取决于。这个问题有很多观点...... 从 JSR-352 Specification View,“线程”:

指定执行此步骤的分区的最大线程数。注意批处理运行时不能保证请求的线程数可用;它将尽可能多地使用到请求的最大值。这是一个可选属性。默认为分区数。

因此,仅从这个角度来看,您应该将此值设置为您想要的任意高(批处理运行时将根据其资源设置真正的限制!)。

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

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

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

从硬件视图来看,您的 CPU 具有线程最大限制。在这个角度下(并且根据经验),将“线程”值设置为等于该值。

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

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

一般来说,如何给出一个赞赏的分区计划,让每个线程都被占用并保证CPU的平衡?

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

希望这有助于...

于 2016-08-01T21:32:28.443 回答