我正在尝试优化程序核心中的一些算法,我想知道硬件的哪一部分真的“减慢了”所有内容。
在编程时,硬件可能最重要的两个部分是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工作并减少内存分配 - 或只计算一次计算值并将其写入内存?什么会给我的算法带来更多性能? 今天现代硬件中的哪些部分真正减慢了代码的速度?
提前致谢。
答案 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访问时间。
优化算法时我必须考虑的最重要的事情是什么?
最重要的是问自己以下问题:
在没有特定硬件的情况下手动优化代码没有任何意义。
现代硬件中的哪些部分真的会让代码速度变得如此之快?
现代硬件通常速度非常快......在PC的情况下,任何硬盘访问都可能是硬件瓶颈。但实际上减慢代码速度的大多数事情都是软件。程序中的数据混洗和嵌套循环。 Bombastic库和您的应用程序使用的各种运行时废话。令人难以置信的缓慢桌面操作系统,同时运行数百个其他程序。等等。
答案 2 :(得分:1)
无论你在想什么,后端都可能不会发生类似的事情。 如今编译器足够聪明,可以尽可能地优化您的程序。 所以如果任何其他程序逻辑没有变化,你的思考(计数/ 10/10/10/10)将用(count / 10000)进行优化。
我发现代码中的另一件事是:如果你已经知道了矢量的大小,那么首先将它分配,这可能会提高你的性能。至于每次增加不必要的计算时,找到存储数据的新位置。
另一种情况虽然CPU速度远远高于内存,但你不能只说存在问题而不是CPU。对代码进行一次描述,找出实际瓶颈的位置。