我有大量对象可以序列化为 array<double, 5>
,让我们称他们为stuff
, 我想将所有这些对象合并成一个大的 vector<double>
, 称之为 data
,用于在离散本地/远程节点之间进行同步的消息传递。
我认为使用 move 语义将 stuff 的数据 move 到 data 应该给我带来巨大的性能提升复制数据,但在测试中,它实际上在 Debug模式下执行得相当慢,而在 Release模式下稍微慢一些。我在想是否有一种标准的方法来实现最佳性能?以下是我使用的实现:
std::vector<std::array<double, 5> > stuff(2000);
std::vector<double> data;
data.reserve(10000);
1)
for (auto & b : stuff) {
data.insert(data.end(), std::make_move_iterator(b.begin()),
std::make_move_iterator(b.end()));
}
2)
for (auto & b : stuff) {
for (auto & item : b) {
data.emplace_back(std::move(item));
}
}
3)
for (auto & b : stuff) {
std::move(b.begin(), b.end(), std::back_inserter(data));
}
4)
for (auto & b : stuff) {
for (const auto & item : b) {
data.emplace_back(item);
}
}
附言:
我正在使用带有 -O3 -march=native -mavx
标志的 g++
最佳答案
首先,std::move 可以提高性能,但它只对拥有某种资源的复杂类型有效。看这个例子:
class MyVector {
double* data;
size_t size;
...
MyVector(MyVector&& rhs) :
data(rhs.data),
size(rhs.size)
{}
MyVector(const MyVector& rhs) :
data(new double[rhs.size]),
size(rhs.size)
{
std::copy(rhs.data, rhs.data+size, data);
}
...
};
对于我们的 MyVector
, move 操作会更快,因为可以绕过数据的分配和深拷贝,只需要一个赋值。我们不为 size 属性保存任何时间,因为它是要分配的,就像在复制构造函数中一样。
对于不包含任何资源的类型(如示例中的内存), move 语义不会提高性能。所有属性都必须写入新位置,而我们是否可以删除旧对象并不重要。
在您的情况下,您尝试 move double
值,无论您是否使用 move 语义,都必须将这些值复制到新位置。您看到性能损失的原因可能是因为您阻止编译器对数据执行单个 memcopy。执行一次内存复制操作通常比按元素复制更快。
执行复制的最快方法很可能是 std::memcpy
,然后是 std::copy
,它专门用于使用 std::memcpy
用于普通类型。您可能看不到速度的提高,因为编译器识别出您想要复制大量 double 并优化您的代码以无论如何使用 memcpy。如果您想了解发生了什么,可以使用 objdump 或 gdb 检查 asm 代码。
关于c++ - 使用 move::semantic 将大量 vector 合并为一个更大的 vector ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44712555/