【问题标题】:How to find the source of memory contention?如何找到内存争用的根源?
【发布时间】:2020-12-25 19:20:09
【问题描述】:

我写了一个程序来做一些并行计算,像这样:

public void multiThreadedRun(int nThreads) throws InterruptedException {
    Thread [] threads = new Thread[nThreads];
    // create and start nThreads ...
    for (int i = 0; i < nThreads; ++i) {
        // ... where each thread runs a task-grabbing loop in this::work.
        threads[i] = new Thread(this::work);
        threads[i].start();
    }

    System.out.println("all threads started, waiting for them to finish....");
    for(int i = 0; i < nThreads; ++i)
        threads[i].join();
    System.out.println("all threads finished.");
}

在具有 96 个内核和 192GB 内存的 c5.24xlarge EC2 实例上运行此程序,使用 java -Xms150g -Xmx150g -XX:+UseParallelGC(使用 AWS 的 Corretto jdk),我将上述 multiThreadedRun 方法的执行时间设置为 nThreads 等于 1、8 和 96。运行时间(相当一致):285、63 和 42秒。

因此,与单线程运行相比,8 个线程提供 4.5 倍的加速,而 96 个线程仅提供 6.8 倍的加速。我怎样才能弄清楚是什么限制了加速?

我相信有争议的资源是内存,因为

一个。这是一个不启动任何 I/O 的计算任务,应该很容易适应分配给堆的 150GB(所以我不希望有太多的虚拟内存 I/O)。

b.在 96 个线程上运行时,我每隔几秒调用一次 jstack &lt;pid&gt; 并汇总结果(对于执行 work() 的 96 个线程):1844 个样本找到了处于“RUNNABLE”状态的线程,只有 76 个找到了它等待监视器。因此,似乎没有太多时间花在等待锁上(但也许jstack 存在抽样偏差?或者这种排除锁争用的方法可能存在其他问题?)。

假设这确实是内存问题,如何诊断内存争用的来源?

更具体地说:

  • “差异分析”(比较在 nThreads = 96 运行和 nThreads = 1 或 nThreads = 8 运行中花费的时间)有用吗?请注意,我不是询问如何使用分析来加速我的代码 - 而是我试图了解比较分析结果是否有助于找出内存争用的位置 - 以及如何。

  • 是否有工具可以查看不同变量在每个缓存层中花费的时间,以及触发缓存刷新的原因?

  • 我猜测哪些对象会导致内存争用。有什么方法可以检验这些假设吗?

【问题讨论】:

  • 这段代码在多少核的机器上运行?
  • @dreamcrash 这是一台 96 核机器(或者更准确地说,这是一个应该表现得像 96 核机器的 EC2 实例......)
  • aws.amazon.com/ec2/instance-types/c5(c5.24xlarge 位于中间附近)
  • 他们确实有类似的“裸机”实例,我可以尝试,但通常更难获得......
  • 感谢您的信息,我添加了标签多线程,以便更多选择可以查看您的问题

标签: java multithreading parallel-processing profiling jstack


【解决方案1】:

我会用 perf 看看你的 CPU 在做什么。如果 CPU 争用内存,它们的 IPC 应该较低,因为它们会在内存访问上停滞不前。您可以查看 toplev 以深入了解实际花费的时间,而不会迷失指标。

另一个技巧,您可以将其应用于具有固定数量线程的同一进程。所以只有 1 个进程、2 个进程、3 个进程等。看看你的系统扩展性如何。如果进程受 CPU 限制,我预计性能几乎呈线性增长,直到您达到 50 个左右的核心。

PS:请确保您的程序运行时间足够长,因为 JIT 需要时间来预热。因此,请确保您至少运行几分钟。

【讨论】:

    猜你喜欢
    • 2011-08-28
    • 2012-12-18
    • 2019-03-17
    • 1970-01-01
    • 2012-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多