繁体   English   中英

CPU 利用率

[英]CPU Utilization

Q1。 编写不消耗 CPU 但仍能实现出色性能的代码的最佳实践是什么? 这个问题非常笼统。 我在这里寻求的是列出用于不同环境的不同实践? 进程监视器/任务管理器之外的调试技巧

编辑:我不是在说 IO 绑定进程。 我说的是 CPU 绑定进程。 但是,在这里我不希望我的进程继续占用 CPU。 如果我有一个 4 核机器并且如果我在一个进程中运行四个简单的循环,CPU 消耗会飙升到 400%,直到应用程序/进程运行。

我在这里寻求一些关于这个话题的经验,每个人都会在一段时间内遇到过。 例如,当应用程序在 Windows 上占用 CPU 时,我进行了调试,因为它不断循环以搜索不存在的文件。

如何以两种不同的 CPU 绑定应用程序平稳运行(给出良好响应)的方式编写我的程序?

更新:建议:

  1. 编写好的干净代码,然后分析您的应用程序,然后进行优化。 (感谢泰德的提示)

  2. 重写/重新设计/重构代码比分析和修复代码更容易。

  3. 使用分析器调试您的应用程序

  4. 不要对等待时间长的线程使用自旋锁

  5. 算法选择

这些建议 go 对于初学者理解概念有很长的路要走。

  • 认真使用探查器。 搜索瓶颈时,请不要依赖常识。
  • 了解big-O表示法,记住big-O表示常见算法。
  • 不惜一切代价避免繁忙的等待循环。
  • 如果是嵌入式的,请学习如何使代码适合代码缓存,这有时会使紧密循环的速度提高十倍。
  • 在进行高层分层开发时,请学习如何有效地缓存数据(例如,最大程度地减少DB语句的数量)。

做尽可能少的工作。


由于您已经编辑了原始问题,因此我将在此处添加一些其他想法,以解决您所描述的具体情况。

假设您不知道进程在哪里阻塞(因为您一直在询问调试技巧),您可以仅通过暂停调试器来开始操作,这将停止应用程序的运行,并从那里可以调查所有程序的当前位置。线程,看看是否有一个紧密的循环。

其次,任何像样的探查器都可以轻松地帮助捕获此类情况。 附加探查器,然后将应用程序运行到阻塞点,查看在总运行时中所占比例更大的调用。 从那里您可以继续前进,找到阻塞循环。

找到问题后,最好重新考虑算法,以完全避免这种情况。 如果这不可能,则在线程上引入睡眠命令。 这将允许其他线程进入CPU并提高应用程序和OS的整体响应速度,但以增加操作时间为代价。 多核编程的技巧是确保所有线程在性能和对其他等待任务的考虑之间进行折衷。

在不知道特定语言或操作系统的情况下,我无法就问题的调试器/分析器组合提出建议,但我认为对于大多数成熟的语言,都有不错的解决方案。

首先,编写良好的干净代码。 以最简单的方式做事。 之后,重复执行以下操作,直到对程序速度满意为止:

  1. 剖析其执行。
  2. 查找花费时间最多的零件。
  3. 加快这些部分。

不要陷入委曲你的代码前面的优化名的陷阱。

记住阿姆达尔定律 通过加快已经只占用程序时间1%的速度,您将不会获得明显的改进。 通过加快程序花费大部分时间来完成的工作,可以最大程度地发挥您的优化优势。

如果您纯粹追求CPU使用率的增长,那么您就需要使用big-O表示法。 您需要确定如何使算法以最少的计算量运行。

但是,对于一般性能,我发现CPU使用率是较小的瓶颈之一。

与性能相关的一些更重要的事情是

数据绑定,您是先获取所有数据还是根据需要获取数据。 选择这些方法之一可能是应用程序性能的关键。

您可以减少正在处理的数据吗? 如果您可以轻松将其全部放入内存中,则可以在此处获得性能。 附带说明一下,如果您在内存中放置过多,可能会产生相反的效果。

总而言之,我认为没有通用的性能解决方案。 编写代码(有一些智慧),然后查看它在哪里遇到困难。

我说的是CPU绑定进程。 但是,在这里我不希望我的进程继续占用CPU。 如果我有4台核心计算机,并且在一个进程中运行四个简单的循环,则在应用程序/进程运行之前,CPU消耗高达400%。

您可能需要研究限制机制,以降低空闲状态下的CPU利用率:

在正常情况下,您的代码无需执行任何操作(即“繁忙等待”),甚至会占用CPU周期。

例如,如果一个空的无限循环不需要执行任何其他操作,则它将尽可能快地运行。

但是,在某些情况下,您不想忙于等待,或者在某些平台上,您可能根本想避免它。

一种完成的方法是在空闲时使用睡眠调用,以便系统调度程序可以重新调度所有正在运行的线程。 同样,您可以使用计时器来确定函数的实际更新速率,并且如果不需要运行该代码,则可以避免调用代码(这是游戏或模拟器有时使用的一种机制)。

通常,您将希望避免轮询,而是使用智能数据结构(例如作业队列),这些数据结构提供了相应的可能性,可以相应地自动调整运行时行为,而不必永久检查数据结构本身。

  • 使用惰性值和/或其他类型的缓存
  • 谨慎选择算法
  • 遵循代码优化技术。

  • 计算您的操作记忆。

  • 计算每个操作的时间。
    (大记号)

对于我来说,您是否正在寻找最有效利用CPU的方法,还是在需要处理大量CPU密集型工作的情况下避免使机器陷入瘫痪的方法,对我来说还不是很清楚。

这些是不兼容的。

对于前者,理想情况下,您需要一个操作系统,该操作系统将完全让您完全随心所欲地控制CPU,因此您不必浪费OS本身的CPU周期,更不用说任何其他进程了可能正在运行。

对于后者,好吧,最近我一直在编写一些代码,这些代码使用 设计欠佳的 CPU绑定算法,而新的Intel I7处理器一直是我的救星。 给定四个内核,每个内核都可以运行两个线程,我只是试图将操作系统线程的使用限制为每个应用程序五个或六个,而且我仍然可以使用CPU切换到另一个窗口来运行kill命令。 至少在驱动系统与空间泄漏交换之前。

  • 编写高效的算法和查询。

  • 我们必须专注于最小化上下文切换

    1-只要适用,我们可以使用 BATCH/Async IO。 如果我们多次调用数据库来获取一些数据。 这不仅仅是网络开销。 我们也为 CPU 创造了开销,因为现在我们的进程或线程正在进行这些调用,将不得不多次驱逐 CPU,并且会产生context switching成本。 如果我们批处理这些调用,它将节省网络延迟和 CPU 延迟。 对于异步情况,每当我们的业务逻辑(服务)正在执行时,我们都会编写日志状态,以便如果我们的进程崩溃或我们必须进行调试,我们会分析这些日志语句。 编写这些日志语句是一个 IO。 这导致了连接切换。 如果我们想避免这种情况,我们应该在单独的线程中执行 AsyncIo,这样我们的主线程将保持高效运行。

    2-使用单线程model:js,node.js,NGINX,VoltDB。 使用多个进程的进程做了很多 IO。

    3-最小化线程池大小我们不应该有非常大的线程池。 如果我们有太多线程,很可能一些线程将没有时间在这个 CPU 上执行。 操作系统将一一地给这些线程中的每一个时间,这将导致大量的上下文切换。

    4-虚拟环境中的多进程。 当我们在一台机器上运行多个进程时,我们应该在它们自己的虚拟环境中运行它们,因为如果我们有 4 个进程,它们可能会尝试争夺这台机器上可用的 CPU。 虚拟环境将允许运行具有专用 CPU 配额和 memory 的进程,因此它们不会相互干扰。

好建议在这里。 编写代码越简单,您节省的时间就越多。

我将性能调整视为调试扩展 人们说测量,测量,测量,但我没有。 我只是让程序准确地告诉我问题出在哪里,如果需要的话,可以不经通知就将其插入几次。 通常这是一个惊喜,而且永远不会出错。

根据程序的大小,通常的历史是发现并解决一系列性能问题,每个问题都会带来10%到50%的加速(如果有严重问题,则更多)。 这样可以使整体速度提高10倍。

然后这些样本准确地告诉了我它在做什么,但是我没有想到如果不进行基本的重新设计就如何解决它,意识到如果我一开始就进行了不同的设计,则启动起来会快很多。用。

假设我可以进行重新设计,那么我可以再进行几轮性能查找和修复。 此后,当我到达收益递减点时,我知道它在物理上会尽可能快,并且我可以在组装级别将其单步执行,并观察每条“拉力”的指令以得到答案。

达到这一点确实感到满意。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM