【问题标题】:Threads per Processor每个处理器的线程数
【发布时间】:2008-10-18 16:35:18
【问题描述】:

在 Java 中,有没有一种编程方式来找出 CPU 支持多少并发线程?

更新

澄清一下,我并不是想用线程来敲击 CPU,而且我知道 Runtime.getRuntime().availableProcessors() 函数,它为我提供了我正在寻找的部分信息。

我想知道是否有办法自动调整线程池的大小,以便:

  • 如果我在使用 1 年的服务器上运行,我会获得 2 个线程(每个 CPU 1 个线程 x 任意乘数 2)
  • 如果我在两年后切换到 Intel i7 四核(每个内核支持 2 个线程),我将获得 16 个线程(每个 CPU 2 个逻辑线程 x 4 个 CPU x 2 的任意乘数)。
  • 如果我使用 8 核 Ultrasparc T2 服务器(每个内核支持 8 个线程),我会得到 128 个线程(每个 CPU 8 个线程 x 8 个 CPU x 2 的任意乘数)
  • 如果我在包含 30 台不同机器(可能在不同年份购买)的集群上部署相同的软件,我不需要阅读 CPU 规格并为每台机器设置配置选项。

【问题讨论】:

    标签: java concurrency


    【解决方案1】:

    Runtime.availableProcessors 返回逻辑处理器(即硬件线程)的数量,而不是物理内核。见CR 5048379

    【讨论】:

    • 啊完美!这让我很开心:)
    • 这个答案让我拒绝了一个功能请求,谢谢!!
    【解决方案2】:

    单个非超线程 CPU 内核始终可以运行一个线程。您可以生成大量线程,CPU 将在它们之间切换。

    最佳数量取决于任务。如果这是一项需要大量 CPU 资源且不需要任何 I/O(例如计算 pi、素数等)的任务,那么每个 CPU 1 个线程可能是最好的。如果任务受更多 I/O 限制。就像从磁盘处理信息一样,那么每个 CPU 拥有多个线程可能会获得更好的性能。在这种情况下,可以在 CPU 处理来自先前磁盘读取的信息时进行磁盘访问。

    我建议您对您的情况下的性能如何随每个 CPU 内核的线程数进行扩展测试,并据此做出决定。然后,当您的应用程序运行时,它可以检查availableProcessors() 并决定它应该产生多少线程。 超线程将使单核对操作系统和所有应用程序(包括availableProcessors())显示为 2 个 CPU,因此如果您的应用程序可以使用超线程,您将获得好处。如果没有,那么性能会受到轻微影响,但可能不足以让额外的努力来满足它的需要。

    【讨论】:

    • 我已经在使用 availableProcessors 来获取 CPU 的数量。我想做的是进一步调整我的线程池的大小,以便在英特尔的 HT 或其他一些多线程技术可用时,我可以利用它。
    • 英特尔 HT 将显示在从 availableProcessors 返回的值中。如果你有一个带 HT 的双核 CPU,那么 availableProcessors 将返回 4。
    • 对可用处理器的投票将返回线程路径数,而不是内核数。甚至操作系统工具也会看到这一点,例如检查使用历史记录下的 Windows 任务管理器,您将被告知您有 4 个 CPU 用于 2 个具有超线程的内核。在 Linux 上可以看到相同的信息,并且由于 JVM 使用本机线程(在几乎所有实现中),Java 会认为与您的操作系统相同。
    【解决方案3】:

    没有标准的方法来获取 Java 中每个 CPU 内核支持的线程数。您最好的选择是获取一个 Java CPUID 实用程序,该实用程序可以为您提供处理器信息,然后将其与您必须生成的表进行匹配,该表为您提供处理器管理的每个内核的线程,而无需“真正的”上下文切换。

    【讨论】:

    • 从我一直在做的所有谷歌搜索来看,情况似乎确实如此:(不过,感谢 CPUID 实用程序的想法。它并不完全理想,但它与我想要的足够接近。
    【解决方案4】:

    每个处理器或处理器内核一次只能执行一件事。使用超线程,情况会有所不同,但在大多数情况下仍然如此,这就是为什么我的 HT 机器在工作中几乎从未超过 50%,即使它达到 100%,它也不会一次处理两倍.

    您可能只需要对计划部署的常见架构进行一些测试,以确定您希望在每个 CPU 上运行多少线程。如果您正在等待大量 I/O,那么仅使用 1 个线程可能会太慢。运行大量线程会减慢速度,因为处理器必须更频繁地切换线程,这可能会非常昂贵。我不确定您可以运行多少线程是否有任何硬编码限制,但我保证在您达到任何硬​​限制之前,您的应用程序可能会因过多的线程切换而爬行。最终,您应该将它作为一个选项保留在配置文件中,以便您可以轻松地将应用程序调整到运行它的任何处理器。

    【讨论】:

    • 如果我实际上不能在声称每个核心支持两个线程的 CPU 上同时运行 2 个 Java 线程,我会觉得有点奇怪。我对 CPU 厂商说法的理解有误吗?
    【解决方案5】:

    CPU 通常不会限制线程数,而且我认为 Java 本身不会限制它将产生的本机(内核)线程数。

    Runtime 类中有一个方法availableProcessors()。这就是你要找的吗?

    【讨论】:

    • 我在某处读到有一个硬限制(Java 强加)在 32k 的范围内。实际上,您的应用会在此之前很久就停止运行。
    • 是的,可能。 Java 并非旨在使用数千个线程。
    • 我假设当您说限制时,您指的是模拟并发(而不是真正的硬件并发)。不是这样吗?
    • 线程数的通常限制是地址空间。在 32 位系统上,您可以通过减小最大堆栈大小来获得更多线程。现代 64 位操作系统应该能够处理数十万个线程。
    【解决方案6】:

    基础知识: 加载到内存中的应用程序是一个进程。一个进程至少有 1 个线程。如果需要,您可以在进程中创建任意数量的线程(理论上)。所以线程的数量取决于你和你使用的算法。

    如果你使用线程池,这意味着线程池管理线程的数量,因为创建线程会消耗资源。线程池回收线程。这意味着许多逻辑线程可以一个接一个地在一个物理线程中运行。

    您不必考虑线程数,它由线程池算法管理。线程池为服务器和台式机 (OS) 选择不同的算法。

    编辑1: 如果您认为线程池不使用您拥有的资源,您可以使用显式线程。在这种情况下,您可以显式管理线程数。

    【讨论】:

    • 英特尔 i7 声称的每核 2 个逻辑线程(或在 Sun T2 的情况下每核 8 个线程)是否没有为多线程应用程序提供比多核硬件提供的更多优势?如果所有 CPU 制造商都是这样,那么我只需要 availableProcessors()。
    • 我很难相信我的应用在每核 8 线程的机器上运行时会卡在每核 2 线程池中。
    • 您确实必须考虑线程数。大多数线程池(许多应用服务器,内置 Java ExecutorService)都需要明确配置上线程绑定。
    • 可以设置面线界限。我使用 .NET,您也可以设置该值,但线程池管理此环境中的线程数。
    • 很好的答案,但我对“这意味着许多逻辑线程可以一个接一个地在一个物理线程中运行”有点困惑。你认为什么是逻辑线程?您不应该将其命名为 Runnable 或 Task 以避免混淆吗?
    【解决方案7】:

    这是虚拟机的功能,而不是 CPU。它与每个线程消耗的堆数量有关。当堆上的空间用完时,就完成了。与其他海报一样,我怀疑如果您由于线程数超过堆空间,您的应用在此之前将无法使用。

    看到这个discussion

    【讨论】:

      猜你喜欢
      • 2019-04-23
      • 1970-01-01
      • 1970-01-01
      • 2013-07-22
      • 1970-01-01
      • 2011-04-10
      • 2018-10-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多