优化代码 - CPU与内存

时间:2014-02-26 07:51:34

标签: c++ c performance algorithm memory

我正在尝试优化程序核心中的一些算法,我想知道硬件的哪一部分真的“减慢了”所有内容。

在编程时,硬件可能最重要的两个部分是CPU和RAM(以及CPU的高速缓冲存储器)。但是在性能方面他们如何一起玩?

考虑这段代码:

std::vector<int> vec;
for(int count = 0; count < 100000; count++)
{
    vec.push_back(count);
}

在这种情况下,真正减慢算法速度的部分是将内存写入RAM的速度(?)。 CPU的速度几乎不会对这段代码的执行时间产生任何影响,因为计算量不大,对吧?

但是现在,请考虑这段代码:

std::vector<int> vec;
for(int count = 0; count < 100000; count++)
{
    vec.push_back(count/10/10/10/10);
}

在这种情况下,在插入列表(在RAM上)之前,(在CPU上)执行几个算术运算。这种情况会对性能产生重大影响吗? CPU必须首先计算结果然后结果可以写入RAM,所以它必须绝对慢,对吗?

如果这是正确的,那么(据我所知),真正减慢程序速度的部分是SPEED,可以写入RAM而不是CPU的速度,对吧?因为即使有一个更复杂的代码块,它也将始终采用以下形式:

//calculate something and write it to the RAM
int something = calculateSomething();

总会有算术运算和内存分配。但是,在查看任务管理器时,我很少看到CPU正在100%工作 - 结论是必须有另一部分减慢整个事情。

要说明问题: 优化算法时我必须考虑的最重要的事情是什么?分配更少的内存并更频繁地重新计算值会增加CPU工作并减少内存分配 - 或只计算一次计算值并将其写入内存?什么会给我的算法带来更多性能? 今天现代硬件中的哪些部分真正减慢了代码的速度?

提前致谢。

3 个答案:

答案 0 :(得分:2)

即使使用今天的硬件,也可以估计一些事情:算术运算的性能有些可预测,您可以将一组操作所需的时间计算为各个操作所需的时间总和。粗略地,高达两倍左右。不幸的是,大多数其他操作都是不可能的。从内存中读取值可能需要1到200个时钟周期。条件跳转的数字类似,具体取决于分支预测和跳转到的代码的缓存状态。而且因为这些操作通常会占用大部分性能,所以很难通过查看代码来猜测瓶颈。 使用分析器并为一些意外做好准备。计算平方根可能比从内存中读取结果更快。 O(n ^ 2)算法可以比O(n)算法更快。在某些情况下,如果编译器可以证明结果保持不变,则编译器甚至可以将其中一个转换为另一个。

答案 1 :(得分:2)

  

在这种情况下,真正减慢算法速度的部分是将内存写入RAM的速度(?)。

不,真正减慢算法速度的部分不是硬件,而是C ++向量的实现,它主要依赖于动态内存分配。它必须在该循环中反复重新调整向量的大小。此外,它将导致堆碎片。所有这些都将成为主要瓶颈。

如果使用普通的“C风格”数组,瓶颈可能是CPU或RAM访问时间。这取决于代码运行的硬件。数据高速缓存不太可能有任何帮助,因为写入后不会立即使用数据。

  

在这种情况下,在插入列表

之前,会在CPU上执行几个算术运算

不,编译器已将您的代码翻译为count/10000。所以有一个CPU分区指令。它不会对32位或更高CPU的性能产生很大影响。在8位CPU上,它会导致严重的性能下降,因为它不可能以有效的方式对大数字进行除法。

  

如果这是正确的

从上面可以看出,大部分都不是。

  

但是,在查看任务管理器时,我很少看到CPU正在100%工作 - 结论是必须有另一部分会减慢整个事情。

在PC上,有一个OS在后台运行。因此,除了在操作系统之上运行的应用程序之外,几乎总会执行某些操作。调度和物理CPU核心数量也将决定使用的CPU的百分比。当然,每种硬件都会发挥作用,不仅是RAM,还有HD访问时间。

  

优化算法时我必须考虑的最重要的事情是什么?

最重要的是问自己以下问题:

  • 是否真的需要优化这段代码?您是否存在一个真正的瓶颈,或者您是否看到了现实世界中存在的问题?
  • 你真的知道预处理器和编译器的优化器是如何工作的吗?
  • 您是否真的知道编译器如何将C ++代码转换为机器代码?
  • 您是否拥有给定系统的深入硬件知识,以至于您对硬件了解的程度远远超过为给定硬件制作编译器端口的人员?您是否对CPU的硬件优化功能有深入的了解,例如流水线,数据/指令缓存,分支预测?

在没有特定硬件的情况下手动优化代码没有任何意义。

  

现代硬件中的哪些部分真的会让代码速度变得如此之快?

现代硬件通常速度非常快......在PC的情况下,任何硬盘访问都可能是硬件瓶颈。但实际上减慢代码速度的大多数事情都是软件。程序中的数据混洗和嵌套循环。 Bombastic库和您的应用程序使用的各种运行时废话。令人难以置信的缓慢桌面操作系统,同时运行数百个其他程序。等等。

答案 2 :(得分:1)

无论你在想什么,后端都可能不会发生类似的事情。 如今编译器足够聪明,可以尽可能地优化您的程序。 所以如果任何其他程序逻辑没有变化,你的思考(计数/ 10/10/10/10)将用(count / 10000)进行优化。

我发现代码中的另一件事是:如果你已经知道了矢量的大小,那么首先将它分配,这可能会提高你的性能。至于每次增加不必要的计算时,找到存储数据的新位置。

另一种情况虽然CPU速度远远高于内存,但你不能只说存在问题而不是CPU。对代码进行一次描述,找出实际瓶颈的位置。