我正在尝试分配和使用100 MB的数据(size_t s = 100 * 1024 * 1024
),并在C ++中测量了不同的方式:
没有初始化的原始分配:
// < 0.01 ms
auto p = new char[s];
C ++零初始化:
// 20 ms
auto p = new char[s]();
手动归零:
// 20 ms
auto p = new char[s];
for (auto i = 0; i < s; ++i)
p[i] = 0;
这不是我的记忆限制,如再次写入记忆所证明的那样:
// 3 ms
std::memset(p, 0xFF, s);
我也尝试了std::malloc
和std::calloc
,但是它们表现出相同的行为。 calloc
返回的内存初始化为零,但是如果我之后执行memset
,则仍然需要20毫秒。
据我了解,未初始化的内存分配速度很快,因为它实际上并没有接触内存。仅当我访问它时,页面才分配给我的程序。设置100 MB的3毫秒对应于〜35GB / s,这可以确定。触发页面错误时,这20毫秒似乎是开销。
有趣的是,这似乎是计算开销。如果我使用多个线程对其进行初始化,它将变得更快:
// 6-10 ms
auto p = new char[s];
#pragma omp parallel for
for (auto i = 0; i < s; ++i)
p[i] = 0;
我的问题:是否有一种方法不仅可以分配内存,还可以立即分配所有页面,从而在访问它时不再出现页面错误?
如果可能,我想避免使用大页面。
(使用std::chrono::high_resolution_clock
进行测量)
这是在装有Clang 7(-O2 -march=native
)的台式机系统(5Ghz i9、3600 MHz DDR4,Linux Mint 19、4.15.0-45通用内核)上完成的,着眼于程序集,编译器不是问题。
编辑:这是一个简化的示例,在我的实际应用程序中,我需要使用一个不同于0的值来初始化它,但这根本不会改变时序。