- 主题:std::vector中初始化与否导致性能差异巨大
你这每个循环的时间是1.4ns?感觉是优化了吧。可能两种代码优化方式不一样?
【 在 xieyf (绿蚁新醅酒,红泥小火炉) 的大作中提到: 】
: 标 题: Re: std::vector中初始化与否导致性能差异巨大
: 发信站: 水木社区 (Sun Feb 27 01:00:35 2022), 站内
:
: gcc执行结果(带初值):
: time elapsed for allocation finished : 0.04800000(s)
: time elapsed for assignment finished : 0.01400000(s)
:
: 如果不带初值定义vv, 结果如下
: time elapsed for allocation finished : 0.00000000(s)
: time elapsed for assignment finished : 0.05200000(s)
:
:
:
: --
:
: ※ 来源:·水木社区
http://www.mysmth.net·[FROM: 120.244.224.*]
--
FROM 73.223.52.*
应该是触发了page fault
【 在 xieyf (绿蚁新醅酒,红泥小火炉) 的大作中提到: 】
: 最近碰到一个奇怪的问题, 一个简单的R3对象, 存放在std::vector中.
: 费解的一幕出现了, 如果vv定义的时候, 为每个元素指定初值, 那么后面对vv进行写操作就飞快.
: 而如果vv定义的时候, 不指定初值, 那么后面对vv写操作的时候, 就花费大约前一种3倍的时间.
: ...................
--
FROM 114.85.144.*
我32GB的物理内存, 也会有page fault问题吗?
win10 确实有page file, 但是linux下我是禁用了swap分区的, 这个按说不会有page fault了吧.
【 在 javaboy 的大作中提到: 】
: 应该是触发了page fault
:
--
FROM 120.244.224.*
intel i7-9700k, 32GB内存.
win10 ltsc 2019
【 在 mvtec 的大作中提到: 】
: 你把你机器的配置贴一下
--
FROM 120.244.224.*
感觉是内存分配器虚实转换时机不同造成的
vector申请了一大块内存,内存分配器只是给出了逻辑地址
当访问具体数据时,OS才会映射到物理地址
构造时给初值,算是访问大块连续逻辑空间,OS映射到物理地址效率高
构造时不给初值,OS只会把当前逻辑地址所在页面映射到物理页面
想必效率是没有前者高的
【 在 xieyf (绿蚁新醅酒,红泥小火炉) 的大作中提到: 】
: 最近碰到一个奇怪的问题, 一个简单的R3对象, 存放在std::vector中.
: 费解的一幕出现了, 如果vv定义的时候, 为每个元素指定初值, 那么后面对vv进行写操作就飞快.
: 而如果vv定义的时候, 不指定初值, 那么后面对vv写操作的时候, 就花费大约前一种3倍的时间.
: ...................
--
FROM 111.197.236.182
嗯, 我搜了一下, c++ 有个lazy allocation机制, 意思就是malloc的时候, 分配的虚拟内存, 只有第一次使用的时候, 才提交成物理内存.
应该是这个问题没跑了
直接换成内存池jemalloc, 性能涨了许多, 不过这个现象仍然在.
都不初始化vector,
========= debug 模式(千万单元)=========
test with malloc, vector un-initialized
time elapsed for allocation finished : 0.77000000(s)
time elapsed for assignment finished : 1.45100000(s)
test with je-malloc, dyna-array un-initialized
time elapsed for allocation finished : 0.02800000(s)
time elapsed for assignment finished : 0.20400000(s)
==============release 模式==============
test with malloc, vector un-initialized
time elapsed for allocation finished : 0.00000000(s)
time elapsed for assignment finished : 0.05400000(s)
test with je-malloc, dyna-array un-initialized
time elapsed for allocation finished : 0.00000000(s)
time elapsed for assignment finished : 0.03500000(s)
【 在 jjfz 的大作中提到: 】
: 感觉是内存分配器虚实转换时机不同造成的
: vector申请了一大块内存,内存分配器只是给出了逻辑地址
: 当访问具体数据时,OS才会映射到物理地址
: ...................
--
FROM 120.244.224.*
这个不是commit还是不commit的问题
commit只是说,保证这块内存地址能用,不会冲突,但是并不代表地址的内容会进cpu缓存。
你现在观察到的现象是:如果object的内存被访问过一次(你的例子里是用assignment操作),那么后访问都会很快。这个我敢说,是cpu cache和内存之间同步的事
你可以把ctor改成
R3(double x, double y, double z)
{
x = m_data[0], y = m_data[1], z = m_data[2];
}
只要这行不被优化掉,保证m_data都被cpu过了一遍读到cache里,后面的访问应该也是一样快
【 在 xieyf 的大作中提到: 】
: 我现在怀疑new出来的内存是没有commit的。
: 访问一遍后, vv中所有内容都是commited, 所以访问起来就快了。
: 这只是一种猜测.
: ...................
--
FROM 122.224.174.*
【 在 ziqin 的大作中提到: 】
: 这个不是commit还是不commit的问题
: commit只是说,保证这块内存地址能用,不会冲突,但是并不代表地址的内容会进cpu缓存。
: 你现在观察到的现象是:如果object的内存被访问过一次(你的例子里是用assignment操作),那么后访问都会很快。这个我敢说,是cpu cache和内存之间同步的事
: ...................
你们说的都两个级别上的东西啊。
他说的是虚拟内存在被真的用到之前不一定真的会对应到物理内存。
你说的是CPU cache和内存之间访问速度区别,以及cache不命中。
两种都有可能导致慢。
--
FROM 1.91.33.*
但是他一开始的问题是:
vector中初始化与否导致性能差异巨大
【 在 hongdiao 的大作中提到: 】
:
: 你们说的都两个级别上的东西啊。
: 他说的是虚拟内存在被真的用到之前不一定真的会对应到物理内存。
: ...................
--
FROM 115.199.178.*
应该还是cache的问题,随便写了一个跑了一下,总时间肯定还是不初始化的最好。
#include <chrono>
#include <functional>
#include <iostream>
namespace {
constexpr int POPULATION = 10000000;
struct R3 {
R3() = default;
R3(double x, double y, double z) {
data[0] = x;
data[1] = y;
data[2] = z;
}
double data[3];
};
void report(const std::function<void()> &f1, const std::function<void()> &f2, bool run_f2_again = false) {
auto start = std::chrono::high_resolution_clock::now();
f1();
auto end = std::chrono::high_resolution_clock::now();
std::cout << "Allocation done in " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start) << std::endl;
start = std::chrono::high_resolution_clock::now();
f2();
end = std::chrono::high_resolution_clock::now();
std::cout << "Assignment done in " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start) << std::endl;
if (run_f2_again) {
start = std::chrono::high_resolution_clock::now();
f2();
end = std::chrono::high_resolution_clock::now();
std::cout << "Assignment again in " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start) << std::endl;
}
std::cout << std::endl;
}
void func1() {
std::vector<R3> rr;
report([&rr]() { rr.reserve(POPULATION); },
[&rr]() {
for (int i = 0; i < POPULATION; ++i) {
rr[i] = {(double) i * 2, (double) i + 4, (double) i + 6};
} });
}
void func2() {
std::vector<R3> rr;
report([&rr]() { rr.assign(POPULATION, R3{0, 0, 0}); },
[&rr]() {
for (int i = 0; i < POPULATION; ++i) {
rr[i] = {(double) i * 2, (double) i + 4, (double) i + 6};
} });
}
void func3() {
std::vector<R3> rr;
report([&rr]() { rr.assign(POPULATION, R3()); },
[&rr]() {
for (int i = 0; i < POPULATION; ++i) {
rr[i] = {(double) i * 2, (double) i + 4, (double) i + 6};
} });
}
}// namespace
int main() {
func1();
func2();
func3();
return 0;
}
【 在 ziqin 的大作中提到: 】
: 但是他一开始的问题是:
: vector中初始化与否导致性能差异巨大
:
: ...................
--
FROM 222.129.53.*