为什么我不能在java中的并行内存绑定应用程序中实现期望的加速?

为什么我不能在java中的并行内存绑定应用程序中实现期望的加速?,java,parallel-processing,Java,Parallel Processing,我的应用程序内存有限。我使用生产者-消费者算法。生产者生成大量大对象(2000万条输入数据集记录超过60 Gig),消费者从共享队列获取它们。 当我放大输入数据集时,速度会急剧下降。我监视了GC,但它似乎没有中断应用程序。我无法使用16个线程实现超过6个的加速。我使用以下热点参数来运行我的应用程序和使用JDK1.8。请帮帮我 -Dfile.encoding=UTF8 -d64 -Xms200G-Xmx200G -详细:gc -XX:+PrintHeapAtGC -XX:+PrintGCDetai

我的应用程序内存有限。我使用生产者-消费者算法。生产者生成大量大对象(2000万条输入数据集记录超过60 Gig),消费者从共享队列获取它们。
当我放大输入数据集时,速度会急剧下降。我监视了GC,但它似乎没有中断应用程序。我无法使用16个线程实现超过6个的加速。我使用以下热点参数来运行我的应用程序和使用JDK1.8。请帮帮我

  • -Dfile.encoding=UTF8
  • -d64
  • -Xms200G-Xmx200G
  • -详细:gc
  • -XX:+PrintHeapAtGC
  • -XX:+PrintGCDetails
  • -XX:+PrintGCTimeStamps
  • -XX:+PrintGCApplicationStoppedTime
  • -XX:+UseConMarkSweepGC
  • -XX:ParallelCMSThreads=2
  • -XX:NewRatio=1
  • -XX:-使用偏置锁定
  • -XX:+PrintSafepointStatistics
  • -XX:PrintSafepointStatisticsCount=1

  • 这不是GC调优问题,您必须对应用程序进行调优以保持非常小的工作集,如果这不是一个选项,您将无法同时使用所有内核,因为瓶颈不是CPU能力

    假设你在一台16核的机器里装了一个插座

    您有16个32 KB的L1数据缓存。当您访问这些时,您将获得线性可伸缩性。使用的内核越多越好。理想情况下,您希望尽可能多地留在一级缓存中以获得全速

    您有16个256 KB的二级缓存。同样,访问是可扩展的,但速度要慢3倍左右

    您有一个大约40 MB的L3缓存。访问是稍微并发的,但通常很难获得2倍的可伸缩性,并且比一级缓存慢10-20倍

    基本上,除非您留在二级缓存中,否则可伸缩性将是一个问题。事实上,由于L3的速度要慢得多,而且是共享的,所以您只需要访问量的1/160(慢16*10倍)就可以访问L3缓存,这样您的平均内存访问量就可以从~1ns降至~2ns。这只占语言中所有随机访问的0.6%,在这种语言中,您只能间接控制内存访问


    显然,如果你有超线程,你的三级缓存会更具竞争力。

    最好的加速取决于代码,一些jvm参数可能会加速代码1,有些参数会降低同一代码的速度,如果没有代码和机器上的信息,我们无法判断那里发生了什么。@Ferrybig您能告诉我哪些参数可能会降低加速比,在什么情况下会降低加速比吗?@StepTNT:我有一棵树,每个节点都有类似p(x,y,z)的数据结构。然后,生产者将根据输入数据集的大小(即p(a1、b1、c1)、p(a2、b2、c2),…)将每个节点生成数千个节点,并将它们放入共享队列中。然后生产者获取它们并对它们执行其他指令。您有多少L3缓存和numa区域。如果是1、2或4,这就是您在内存带宽方面的可伸缩性。感谢您的回答和时间!现在这个问题对我来说更清楚了。以前,我认为问题来自内存限制或GC,并认为如果使用“堆外内存”,它会起作用。我的应用程序不是CPU密集型的。我的应用程序中唯一的操作符是“比较”,我的主要算法是带多项式大(O)的回溯算法。因此,在我看来,即使我再次减小数据集的大小,也无法实现理想的CPU利用率。你认为我的问题本质上不是可并行的吗?@nasim重要的是要找出瓶颈,而你的瓶颈很可能是内存访问。是的,我认为内存是瓶颈。那么您对这种类型的程序有什么建议或解决方案吗?@nasim您需要在设计应用程序时考虑如何最大限度地减少内存访问。这可能意味着使用较小的数据类型,但更重要的是考虑应用程序执行的随机访问的数量。这假设您已经最小化了分配率,降低分配率意味着您用更少的时间填充CPU缓存以提高其效率。我真的很感激!我在找飞行记录器之类的东西!以前,我使用visualVM来监视我的应用程序,但信息量不够。这真是太棒了!