我只是想知道这是否是C ++中的预期行为。下面的代码大约在0.001毫秒运行:
for(int l=0;l<100000;l++){
int total=0;
for( int i = 0; i < num_elements; i++)
{
total+=i;
}
}
但是如果将结果写入数组,则执行时间最多可达15毫秒:
int *values=(int*)malloc(sizeof(int)*100000);
for(int l=0;l<100000;l++){
int total=0;
for( unsigned int i = 0; i < num_elements; i++)
{
total+=i;
}
values[l]=total;
}
我可以理解写入数组需要时间,但时间是否成比例?
为每个人欢呼
答案 0 :(得分:11)
第一个例子可以仅使用CPU寄存器来实现。这些可以每秒访问数十亿次。第二个例子使用了如此多的内存,它确实溢出了L1和可能的L2缓存(取决于CPU模型)。那会慢一些。然而,15 ms / 100.000写入每次写入1.5 ns - 667 Mhz有效。那是不慢。
答案 1 :(得分:10)
看起来编译器在第一种情况下完全优化了循环。
循环的总效果是无操作,因此编译器只是删除它。
答案 2 :(得分:3)
这很简单。 在第一种情况下,您只有3个变量,可以很容易地存储在GPR(通用寄存器)中,但这并不意味着它们一直存在,但它们可能在L1高速缓存中,这意味着它们可以可以非常快速地访问。
在第二种情况下,您有超过100k的变量,并且您需要大约400kB来存储它们。这对于寄存器和L1高速缓冲存储器来说是非常有用的。在最好的情况下,它可能在L2缓存中,但可能并非所有这些都在L2中。如果没有注册的东西,L1,L2(我假设您的处理器没有L3),这意味着您需要在RAM中搜索它,并且需要花费更多的时间。
答案 3 :(得分:1)
我怀疑你所看到的是virtual memory和可能的分页的影响。 malloc
调用将分配一个相当大的内存块,可能由许多虚拟页面表示。每个页面都分别链接到进程内存。
您可能还在测量调用malloc
的费用,具体取决于您为循环计时的方式。在任何一种情况下,性能都会对编译器优化选项,线程选项,编译器版本,运行时版本以及其他任何内容非常敏感。您无法安全地假设成本与分配的大小成线性关系。您唯一可以做的就是测量它并找出一旦被证明是一个问题,如何最好地优化。