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

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

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

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

例如,有表A,B,C要做,它们的行分别是10亿,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平衡?

最佳答案 答案…

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规范视图,“线程”:

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具有线程最大限制.在此视角下(以及经验法则),将“线程”值设置为等于此值.

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

在Summary中,将“threads”值设置为CPU最大线程限制.然后,检查该值是否不会导致阻塞问题;如果是这样,减少价值.另外,验证它是否相应地配置了批处理运行时,它允许您根据需要执行任意数量的线程.

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

避免使用静态分区计划(至少对于您而言).而是使用分区映射器. Partition Mapper是一个实现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分区.

希望这有帮助……

点赞