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

标签 multithreading jakarta-ee jsr352

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的平衡?
  • 最佳答案

    答案...

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

    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 个! (两个作为 worker ,一个作为协调员)......所有这些资源(线程)都来自同一个池!

    总之,最重要的是:调查您正在使用什么 JSR325 实现并相应地设置它 .

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

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

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

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



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

    希望这有助于...

    关于multithreading - 如何在 JSR 352 中定义一个好的分区计划以确保 CPU 平衡?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38675757/

    相关文章:

    java - PDFbox遇到错误(如何计算非简单字体的位置)

    spring-batch - Spring批处理jsr 352跳过限制如何获得无限默认或设置无限

    java - 带有 Liberty Profile 的 JSR 352 - 当 ItemReader 执行数据库查询时如何实现检查点

    c++ - 如果不执行协程,则在pthread段故障之间共享Lua状态

    c - 无法理解 pthread_join()

    c++ - 当作为 Function 的参数传递给线程时,为什么仿函数的 dtor 调用两次(多次)?

    c - 并行矩阵计算

    mysql - 安装 caldecott 时出错

    java - 何时创建新的 EntityManager

    jsr352 - 批处理作业定义: How to run a dynamically-calculated number of partitions?