为什么虚拟循环会消耗内核时间?

beb*_*dek 2 c++ time

我编写了这个简单,无用的程序:

#include <iostream>
using namespace std;
#define TABSIZE 256*1024*1024

int main(){
    volatile int *tab = new int[TABSIZE];

    cerr << "start" << endl;
    for(int i=0;i<TABSIZE;i+=1)
        tab[i] *= i;
    cerr << "stop" << endl;

    delete []tab;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

编译(女巫O2)并与之一起运行后,time ./a.out我对结果感到非常惊讶:

real    0m1,660s
user    0m0,462s
sys     0m1,177s
Run Code Online (Sandbox Code Playgroud)

显然,即使主循环与任何系统调用都没有关系,大部分时间还是花费在内核空间上。我可以start在程序启动后立即看到字符串,因此new不会花费很多时间。同源地,stop在结束之前出现。

因此,问题是:为什么在内核空间上花费了这么多时间?我在Linux 4.15上使用GCC 7.4。

Rus*_*lan 5

volatile int *tab = new int[TABSIZE];
Run Code Online (Sandbox Code Playgroud)

该语句分配1 GiB的RAM。该金额在进程的页表中标记为已使用,但并未真正初始化或可用(这些页被标记为“不存在”)。

tab[i] *= i
Run Code Online (Sandbox Code Playgroud)

此时,第一次访问新页面(通常为4KiB)会导致页面错误,该错误由内核处理,然后内核将内存范围初始化为零并将页面标记为存在。然后,直到下一页,访问都会发生而没有页面错误。

此内存管理是内核CPU使用率的原因。