基于no的线程配置。 CPU核心

场景:我有一个示例应用程序,我有3种不同的系统配置 –

- 2 core processor, 2 GB RAM, 60 GB HHD, - 4 core processor, 4 GB RAM, 80 GB HHD, - 8 core processor, 8 GB RAM, 120 GB HHD 

为了有效地利用我的应用程序的H / Wfunction,我希望配置no。 应用程序级别的线程数。 但是,我希望在彻底了解系统function之后才能这样做。

是否有某种方式(系统/模式/工具)来参考最大值和最小值来确定系统实力。 它可以最佳地服务并且不会降低效率和性能。 通过这种方式,我只能为我的应用程序配置那些能够完全正义并为各自的硬件配置实现最佳性能的值。

Edited1:任何人都可以建议任何关于如何为特定h / w配置设置基线的读数。

编辑2:使其更直接 – 希望学习/了解我可以阅读的任何资源/文章,以便在一般/整体层面上了解线程的CPU管理。

使用的最佳线程数取决于几个因素,但主要是可用处理器的数量以及您的任务的CPU密集程度。 Java Concurrency in Practice提出了以下forms公式来估计最佳线程数:

 N_threads = N_cpu * U_cpu * (1 + W / C) 

哪里:

  • N_threads是最佳线程数
  • N_cpu是prcessors的数量,您可以从Runtime.getRuntime().availableProcessors();
  • U_cpu是目标CPU利用率(如果要使用完整的可用资源,则为1)
  • W / C是等待时间与计算时间的比率(CPU绑定任务为0,慢速I / O任务可能为10或100)

因此,例如,在受CPU限制的情况下,您将拥有与CPU一样多的线程(一些主张使用该数字+ 1但我从未见过它产生了显着差异)。

对于缓慢的I / O过程,例如网络爬虫,如果下载页面的速度比处理速度低10倍,则W / C可能为10,在这种情况下,使用100个线程将非常有用。

但请注意,实际上有一个上限(使用10,000个线程通常不会加快速度,你可能会得到一个OutOfMemoryError,然后才能以正常的内存设置启动它们)。

如果您对运行应用程序的环境一无所知,这可能是您可以获得的最佳估计值。 在生产中分析您的应用程序可能使您可以微调设置。

虽然没有严格的相关性,但您可能也对Amdahl定律感兴趣,该定律旨在测量程序并行化可以带来的最大加速。

我的建议是提供配置和命令行开关,用于分配每台机器的线程数。 在用户/管理员未明确配置应用程序的情况下,使用基于Runtime.getRuntime()。availableProcessors()的启发式算法,如此处的其他答案所示。 我强烈建议不要使用独有的基于启发式的线程到核心猜测,原因如下:

  • 大多数现代硬件正朝着越来越模糊的“硬件线程”方向发展:SMT模型(如Intel的超线程和AMD的计算模块)使公式复杂化(详情如下),并且在运行时查询此信息可能很困难。

  • 大多数现代硬件都具有涡轮增压function,可根据活动核心和环境温度来调整速度。 随着涡轮增压技术的改进,速度范围(ghz)也在增长。 最近的一些英特尔和AMD芯片的范围从2.6ghz(所有核心活动)到3.6ghz(单/双核活动),结合SMT可以意味着每个线程在前一种设计中获得了有效的1.6ghz – 2.0ghz吞吐量。 目前无法在运行时查询此信息。

  • 如果您没有强有力的保证您的应用程序将是目标系统上运行的唯一进程,那么盲目地消耗所有cpu资源可能不会取悦用户或服务器管理员(取决于该软件是用户应用程序还是服务器应用程序) 。

没有强大的方法可以在运行时知道机器其余部分内部的情况,而无需使用您自己的自制多任务内核替换整个操作系统。 您的软件可以尝试通过查询进程和窥视CPU负载等进行有根据的猜测,但这样做很复杂,并且有用性仅限于特定类型的应用程序(您的应用程序可能符合条件),并且通常受益于或要求提升或特权访问级别。

  • 现代病毒扫描仪现在通过设置现代操作系统提供的特殊优先级标志来工作,例如。 他们让操作系统在“系统闲置”时告诉他们。 操作系统的决定不仅仅基于CPU负载:它还考虑了可能由电影播放器​​等设置的用户输入和多媒体标记。这对于大多数空闲任务来说很好,但对于CPU密集型任务(如你的。

  • 分布式家庭计算应用程序(BOINC,Folding @ Home等)通过定期查询正在运行的进程和系统CPU负载来工作 – 可能每秒或每半秒一次。 如果在连续多个查询的不属于应用程序的进程上检测到加载,则应用程序将暂停计算。 一旦负载变低以进行一些查询,它就会恢复。 需要多次查询,因为CPU负载读数因短暂的峰值而臭名昭着。 仍有一些警告:1。仍然鼓励用户手动重新配置BOINC以适应他们的机器规格。 2.如果BOINC在没有Admin权限的情况下运行,那么它将不会知道其他用户(包括某些服务进程)启动的进程,因此它可能与那些CPU资源不公平地竞争。

关于SMT(超线程,计算模块):

如今,大多数SMT都会报告为硬件核心或线程,这通常不太好,因为在SMT系统上的每个核心进行扩展时,很少有应用程序能够以最佳方式执行。 更糟糕的是,查询核心是共享的(SMT)还是专用核心往往无法产生预期的结果。 在某些情况下,操作系统本身根本不知道(例如,Windows 7不知道AMD Bulldozer的共享核心设计)。 如果您可以获得可靠的SMT计数,那么经验法则是将每个SMT计为CPU密集型任务的半个线程,并将其作为大多数空闲任务的完整线程。 但实际上,SMT的重量取决于它所做的计算和目标架构。 例如,英特尔和AMD的SMT实现几乎相互对立 – 英特尔在运行并行加载整数和分支操作的任务方面表现强劲。 AMD擅长并行运行SIMD和内存操作系统。

关于Turbofunction:

如今,大多数CPU都具有非常有效的内置Turbo支持,进一步降低了在系统所有内核中扩展所带来的价值。 更糟糕的是,涡轮增压function有时基于系统的实际温度和CPU负载,因此塔本身的冷却系统会像CPU规格那样影响速度。 例如,在特定的AMD A10(Bulldozer)上,我观察到它在两个线程上以3.7ghz运行。 第三个线程启动时降至3.5ghz,第四个启动时降至3.4ghz。 由于它也是一个集成的GPU,当四个线程加上GPU工作时,它一直下降到大约3.0ghz(A10 CPU在高负载情况下内部优先考虑GPU); 但仍然可以通过2个线程和GPU激活集合3.6ghz。 由于我的应用程序同时使用了CPU和GPU,因此这是一个重要的发现。 通过将进程限制为两个CPU绑定线程(另外两个共享核心仍然有用,它们作为GPU服务线程 – 能够唤醒并快速响应以将新数据推送到GPU,我能够提高整体性能,如所须)。

…但与此同时,我在4x线程上的应用程序在安装了更高质量冷却设备的系统上表现得更好。 这一切都非常复杂。

结论:没有好的答案,而且由于CPU SMT / Turbo设计领域不断发展,我怀疑很快就会有一个好的答案。 你今天制定的任何体面的启发式明天都可能不会产生理想的结果。 所以我的建议是:不要浪费太多时间。 根据核心计数粗略猜测一些适合本地目的的东西,允许它被config / switch覆盖,然后继续前进。

您可以像这样获得JVM可用的处理器数量:

 Runtime.getRuntime().availableProcessors() 

不幸的是,从可用处理器的数量计算最佳线程数并不是微不足道的。 这很大程度上取决于应用程序的特性,例如,CPU绑定的应用程序具有比处理器数量更少的线程,而如果应用程序主要是IO绑定的,则可能需要使用更multithreading。 您还需要考虑系统上是否正在运行其他资源密集型进程。

我认为最好的策略是根据每个硬件配置凭经验确定最佳线程数,然后在应用程序中使用这些数字。

我同意这里的其他答案,建议采用最佳猜测方法,并提供覆盖默认值的配置。

此外,如果您的应用程序特别占用CPU,则可能需要查看将应用程序“固定”到特定处理器。

您没有说明您的主要操作系统是什么,或者您是否支持多个操作系统,但大多数都有一些方法可以做到这一点。 例如,Linux有任务集 。

常见的方法是避免CPU 0(始终由OS使用),并将应用程序的cpu亲和性设置为位于同一套接字中的一组CPU。

保持应用程序的线程远离cpu 0(如果可能的话,远离其他应用程序)通常可以通过减少任务切换量来提高性能。

将应用程序保留在一个套接字上可以通过减少缓存失效来进一步提高性能,因为应用程序的线程在cpus之间切换。

与其他所有内容一样,这在很大程度上取决于您运行的计算机的体系结构,以及运行的其他应用程序。

使用VisualVm工具监视threads.First在程序中创建最小线程并查看其性能。然后增加程序中的线程数并再次分析其性能。这可以帮到你。

我在这里使用这个Python脚本来确定以最佳参数和人体工程学方式启动Java应用程序的内核(和内存等)的数量。 Github上的PlatformWise

它的工作原理如下:编写一个python脚本,调用上面脚本中的getNumberOfCPUCores()来获取内核数,并使用getSystemMemoryInMB()来获取内存。 您可以通过命令行参数将该通知传递给您的程序。 然后,您的程序可以根据内核数使用适当数量的线程。

在应用程序级别创建线程是好的,在多核处理器中,在核心上执行单独的线程以提高性能。因此,为了利用核心处理能力,最佳实践是实现线程。

我的想法:

  1. 一次只有1个程序的线程将在1个核心上执行。
  2. 2个线程的相同应用程序将在2个核心上执行一半。
  3. 使用4个线程的相同应用程序将在4核心上执行得更快。

因此,您开发的应用程序应该具有线程级别<= no of cores。

线程执行时间由操作系统管理,是一种高度不可预测的活动。 CPU执行时间称为时间片或量子。 如果我们创建越来越多的线程,操作系统会花费这个时间片的一小部分来决定哪个线程先行,从而减少每个线程获得的实际执行时间。 换句话说,如果有大量的线程排队,每个线程将做较少的工作。

阅读本文以了解如何实际利用cpu core.Fantastic内容。 csharp-codesamples.com/2009/03/threading-on-multi-core-cpus/

不幸的是,从可用处理器的数量计算最佳线程数并不是微不足道的。 这很大程度上取决于应用程序的特性,例如,CPU绑定的应用程序具有比处理器数量更少的线程,而如果应用程序主要是IO绑定的,则可能需要使用更multithreading。 您还需要考虑系统上是否正在运行其他资源密集型进程。