1

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

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

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

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

更新: 建议:

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

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

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

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

  5. 算法选择

这些建议对初学者理解这些概念大有帮助。

4

9 回答 9

6
  • 虔诚地使用分析器。在寻找瓶颈时不要依赖常识。
  • 学习大 O 表示法,记住常用算法的大 O。
  • 不惜一切代价避免繁忙的等待循环。
  • 在嵌入式的情况下,学习如何使代码适合代码缓存,这有时可以在紧凑的循环中实现十倍的加速。
  • 在进行高级分层开发时,学习如何有效地缓存数据(例如,尽量减少 DB 语句的数量)。
于 2009-05-22T13:38:32.007 回答
6

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

  1. 分析其执行情况。
  2. 找到它花费最多时间的部分。
  3. 加快这些部分。

不要陷入以优化的名义预先扭曲代码的陷阱

记住阿姆达尔定律。通过加速已经只消耗程序 1% 时间的东西,你不会得到明显的改进。通过加快程序花费最多时间的部分,您可以获得最大的优化收益。

于 2009-05-22T14:24:06.487 回答
5

做尽可能少的工作。


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

假设您不知道您的进程阻塞在哪里(因为您要求调试提示),您可以从暂停调试器开始,这将停止应用程序正在执行的任何操作,然后您可以从那里调查所有的当前位置线程,看看它们中的任何一个是否处于紧密循环中。

其次,任何体面的分析器都可以轻松帮助捕捉到这样的情况。附加分析器并将应用程序运行到阻塞点,看看那些显着占总运行时间百分比的调用。从那里您可以返回找到阻塞循环。

一旦你找到了理想的问题,重新考虑算法以完全避免这种情况。如果这不可能,那么在线程上引入睡眠命令。这将允许其他线程进入 CPU 并提高应用程序和整个操作系统的响应能力,但会增加操作运行时间。多核编程的诀窍是确保所有线程在性能和考虑其他等待任务之间做出妥协。

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

于 2009-05-22T13:41:39.753 回答
2

如果你追求的是纯粹的 CPU 使用率增益,那么它就是你需要的大 O 表示法。你需要弄清楚如何让你的算法在尽可能少的计算中工作。

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

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

数据绑定,你是预先获取所有数据还是按需获取。选择其中一种方法可能是您的应用程序性能的关键。

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

我想总结一下,性能没有通用的解决方案。编写你的代码(有一定的智慧),然后看看它在哪里挣扎。

于 2009-05-22T13:43:44.570 回答
2

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

您可能需要研究节流机制以在空闲状态下降低 CPU 利用率:

在正常情况下,您的代码甚至会在不需要执行任何操作(即“忙等待”)时消耗 CPU 周期。

例如,一个空的无限循环将尽可能快地运行,如果它不需要做任何其他事情的话。

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

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

通常,您会希望避免轮询,而是使用智能数据结构(例如作业队列),从而可以相应地自动调整运行时行为,而无需永久检查数据结构本身。

于 2009-05-22T14:45:04.353 回答
1
  • 使用惰性值和/或其他类型的缓存
  • 谨慎选择算法
于 2009-05-22T13:38:03.723 回答
1
  • 遵循代码优化技术。

  • 计算您的操作的内存。

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

于 2009-05-22T13:38:48.603 回答
1

我不太清楚您是在寻找最有效地利用 CPU 的方法,还是在有大量 CPU 密集型工作要做时避免机器陷入困境的方法。

这些是不相容的。

对于前者,理想情况下,您需要一个操作系统,只要您愿意,您就可以完全接管 CPU,因此您不必在操作系统本身上浪费 CPU 周期,更不用说任何其他进程那可能正在运行。

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

于 2009-05-22T14:51:55.260 回答
0

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

我将性能调优视为调试的延伸。人们说测量,测量,测量,但我没有。我只是让程序准确地告诉我问题出在哪里,如果需要的话,我会在不事先通知的情况下多次访问它。这通常是一个惊喜,而且永远不会出错。

根据程序的大小,通常会发现并修复一系列性能问题,每个问题都可以提高 10% 到 50% 的速度(如果出现严重问题,速度会更高)。这提供了大约 10 倍的整体加速。

然后样本准确地告诉我它在做什么,但我想不出如何在没有基本重新设计的情况下修复它,我意识到如果我一开始就以不同的方式进行设计,开始会快得多和。

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

达到这一点真的很满足。

于 2009-05-22T15:52:21.817 回答