San*_*osh 29 java cpu multithreading threadpool akka
场景:我有一个示例应用程序,我有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
Run Code Online (Sandbox Code Playgroud)
为了有效地利用我的应用程序的H/W功能,我希望配置no.应用程序级别的线程数.但是,我希望在彻底了解系统功能之后才能这样做.
是否有某种方式(系统/模式/工具)来参考最大值和最小值来确定系统实力.它可以最佳地服务并且不会降低效率和性能.通过这种方式,我只能为我的应用程序配置那些能够完全正义并为各自的硬件配置实现最佳性能的值.
Edited1: 任何人都可以建议任何关于如何为特定h/w配置设置基线的读数.
编辑2: 使其更直接 - 希望学习/了解我可以阅读的任何资源/文章,以获得对一般/整体级别的线程CPU管理的一些了解.
ass*_*ias 63
使用的最佳线程数取决于几个因素,但主要是可用处理器的数量以及您的任务的CPU密集程度.Java Concurrency in Practice提出了以下形式公式来估计最佳线程数:
N_threads = N_cpu * U_cpu * (1 + W / C)
Run Code Online (Sandbox Code Playgroud)
哪里:
Runtime.getRuntime().availableProcessors();因此,例如,在受CPU限制的场景中,您将拥有与CPU一样多的线程(一些拥护者使用该数字+ 1,但我从未见过它产生了显着的差异).
对于缓慢的I/O过程,例如网络爬虫,如果下载页面的速度比处理速度低10倍,则W/C可能为10,在这种情况下,使用100个线程将非常有用.
但请注意,实际上有一个上限(使用10,000个线程通常不会加快速度,你可能会得到一个OutOfMemoryError,然后才能以正常的内存设置启动它们).
如果您对运行应用程序的环境一无所知,这可能是您可以获得的最佳估计值.在生产中分析您的应用程序可能使您可以微调设置.
虽然没有严格的相关性,但您可能也对Amdahl定律感兴趣,该定律旨在测量程序并行化可以带来的最大加速.
jst*_*ine 15
我的建议是提供配置和命令行开关,用于分配每台机器的线程数.在用户/管理员未明确配置应用程序的情况下,使用基于Runtime.getRuntime().availableProcessors()的启发式,如此处的其他答案所示.我强烈建议不要使用独有的基于启发式的线程到核心猜测,原因如下:
大多数现代硬件正朝着越来越模糊的"硬件线程"方向发展:SMT模型(如Intel的超线程和AMD的计算模块)使公式复杂化(详情如下),并且在运行时查询此信息可能很困难.
大多数现代硬件都具有涡轮增压功能,可根据活动核心和环境温度来调整速度.随着涡轮增压技术的改进,速度范围(ghz)也在增长.最近的一些英特尔和AMD芯片的范围可以从2.6ghz(所有内核有效)到3.6ghz(单/双内核有源),结合SMT可以意味着每个线程在前一种设计中获得了有效的1.6ghz - 2.0ghz吞吐量.目前无法在运行时查询此信息.
如果您没有强有力的保证您的应用程序将是目标系统上运行的唯一进程,那么盲目地消耗所有cpu资源可能不会取悦用户或服务器管理员(取决于该软件是用户应用程序还是服务器应用程序) .
没有强大的方法可以在运行时了解机器其余部分的情况,而无需使用自己的自制多任务内核替换整个操作系统.您的软件可以尝试通过查询进程和窥视CPU负载等进行有根据的猜测,但这样做很复杂,并且有用性仅限于特定类型的应用程序(您的应用程序可能符合条件),并且通常受益于或要求提升或特权访问级别.
现代病毒扫描仪现在通过设置现代操作系统提供的特殊优先级标志来工作,例如.他们让操作系统在"系统闲置"时告诉他们.操作系统的决定不仅仅基于CPU负载:它还考虑了可能由电影播放器等设置的用户输入和多媒体标记.这对于大多数空闲任务来说很好,但对于CPU密集型任务(如你的.
分布式家庭计算应用程序(BOINC,Folding @ Home等)通过定期查询正在运行的进程和系统CPU负载来工作 - 可能每秒或每半秒一次.如果在连续多个查询的不属于应用程序的进程上检测到加载,则应用程序将暂停计算.一旦某些查询的负载变低,它就会恢复.需要多次查询,因为CPU负载读数因短暂的峰值而臭名昭着.仍有一些警告:1.仍鼓励用户手动重新配置BOINC以适应其机器的规格.2.如果BOINC是没有管理员权限运行的话,就不会知道其他用户(包括一些服务流程)启动的进程,因此它可能不公平地与那些对CPU资源的竞争.
关于SMT(超线程,计算模块):
如今,大多数SMT将作为硬件核心或线程进行报告,这通常并不好,因为在SMT系统上的每个核心进行扩展时,很少有应用程序能够以最佳方式执行.更糟糕的是,查询核心是共享的(SMT)还是专用核心往往无法产生预期的结果.在某些情况下,操作系统本身根本不知道(例如,Windows 7不知道AMD Bulldozer的共享核心设计).如果您可以获得可靠的SMT计数,那么经验法则是将每个SMT计为CPU密集型任务的半个线程,并将其作为大多数空闲任务的完整线程.但实际上,SMT的重量取决于它所做的计算和目标架构.英特尔和AMD的SMT实现几乎完全相反,例如 - 英特尔在运行并行加载整数和分支操作的任务方面表现强劲.AMD在并行运行SIMD和内存操作方面表现强劲.
关于Turbo功能:
如今,大多数CPU都具有非常有效的内置Turbo支持,进一步降低了在系统所有内核中扩展所带来的价值.更糟的是,涡轮增压功能有时基于尽可能多的,因为它是在CPU负载系统的真实温度,所以塔本身的冷却系统会影响速度不亚于CPU规格做.例如,在特定的AMD A10(Bulldozer)上,我观察到它在两个线程上以3.7ghz运行.第三个线程启动时降至3.5ghz,第四个启动时降至3.4ghz.由于它是一款集成了GPU中,也一路下降到约3.0GHz的时候四个线程加上GPU进行工作(在A10 CPU内部优先在高负载情况下的GPU); 但仍然可以通过2个线程和GPU激活集合3.6ghz.由于我的应用程序同时使用了CPU和GPU,因此这是一个重要的发现.我能够通过限制处理两个CPU限制的线程(其他两个共享内核仍然乐于助人,他们曾担任GPU服务线程以提高整体性能 - 能够唤醒和快速响应新的数据推到GPU,如所须).
...但与此同时,我在4x线程上的应用程序可能在安装了更高质量冷却设备的系统上表现更好.这一切都非常复杂.
结论:没有好的答案,而且由于CPU SMT/Turbo设计领域不断发展,我怀疑很快就会有一个好的答案.你今天制定的任何体面的启发式明天都不会产生理想的结果.所以我的建议是:不要浪费太多时间.根据核心计数粗略猜测一些适合本地目的的东西,允许它被config/switch覆盖,然后继续前进.
小智 14
您可以获得JVM可用的处理器数量,如下所示:
Runtime.getRuntime().availableProcessors()
Run Code Online (Sandbox Code Playgroud)
不幸的是,从可用处理器的数量计算最佳线程数并不是微不足道的.这在很大程度上取决于应用程序的特性,例如,CPU绑定的应用程序具有比处理器数量更少的线程,而如果应用程序主要是IO绑定,则可能需要使用更多线程.您还需要考虑系统上是否正在运行其他资源密集型进程.
我认为最好的策略是根据每个硬件配置凭经验确定最佳线程数,然后在应用程序中使用这些数字.