2016-07-30 22 views
4

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

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

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

例如,有表A,B,C要做,它们的行数分别为1亿,1百万和1千。该步骤旨在将这些实体处理为文档,一个实体转到一个文档。文件制作的顺序并不重要。这些表的实体的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平衡?
+0

通常,在分区步骤中,您正在运行在每个分区完全相同的逻辑。首先让我问一下,对于你的“表格类型”A,B和C,你是否认为它们非常相似,以至于它们很适合用单一步骤使用相同的逻辑来读取/处理/写入所有三种? (如果不是,可能更适合将它们分成三个连续的步骤,其中一些可以分区,和/或可能分割以同时运行不同的步骤)。 –

+0

嗨@ScottKurz,是的,他们非常适合在同一步骤中运行。其实,[我的物品处理器](https://github.com/mincong-h/gsoc-hsearch/blob/2b3831e0769dbc2c959d2d5a90d89d61699d4796/core/src/main/java/org/hibernate/search/jsr352/internal/steps/lucene/ ItemProcessor.java)将JPA模型转换为Lucene文档以获取全文搜索功能。这与表A,B和C的确切逻辑相同。 –

回答

2

答案...

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

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

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

这就是发生了什么!

一般情况下,有多少线程可我/我应该使用?这是相同数量的CPU核心吗?

这取决于。这个问题有很多的观点...... 从JSR-352规格查看,“线程”:

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

因此,根据只有在这个角度来看,你应该将此值设置为要作为高(批处理运行时将设定真正的限制,根据其资源!)。

从批处理运行时透视图(JSR352 Implementation):任何体面的实现都将使用线程池来执行分区步骤。因此,如果此池的固定大小为N,则无论您设置了多少线程编号,都不会同时执行多于N个的分区。

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

无论如何,这一切的重要之处在于:调查JSR325的实现是否使用并相应地设置它

从硬件查看,你的CPU有一个线程最大限制。在这个观点下(和根据经验),设置“线程”的值等于这样的值。

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

总之在中,将“线程”值设置为与CPU最大线程限制一样高。然后,检查该值是否不会导致阻塞问题;如果是这样,请降低价值。另外,验证它是否相应地配置了批处理运行时,并允许您执行所需的多个线程。

一般情况下,如何给一个赞赏的分区计划,以便每个线程都被占用并确保CPU平衡?

避免使用静态分区方案(至少对你来说)。相反,使用分区映射器。分区映射器是一个实现接口的类,允许以编程方式定义分区计划(多少个分区,多少个线程,每个分区的属性)。因此,对于你的情况,拿你的表(A,B,C),并将它们分成N个块(其中N = 1000)......每个块将是一个分区。你应该用C型的分区启动,并做(表)的实体之间的分区循环赛:C0B0A0B1A1,...,B999A999A1000,... A999999 ...使用该方案中,实体C将首先完成,留下一个线程以解决更多的A和B分区。之后,B将完成,留下更多资源攻击剩余的A分区。

希望这有助于...

+0

我的测试使用JBeret作为实现,但是我的框架本身允许用户选择他们自己的实现(嵌入在目标Java EE容器内的批处理运行时)。所以我会看看所有实现的线程池设置。你已经提到多个工作的并发性和不同视图的表现,这很宝贵。您在摘要中提出的解决方案非常好,我会接受它。感谢这个非常详细和有用的答案@CarlitosWay。 –

相关问题