C++ 使用move::semantic将大量向量合并为更大的向量
我有大量的对象可以序列化成一个C++ 使用move::semantic将大量向量合并为更大的向量,c++,c++11,vector,c++14,move,C++,C++11,Vector,C++14,Move,我有大量的对象可以序列化成一个数组,让我们称它们为东西,我想将所有这些对象合并成一个大的向量,称之为数据,用于在离散的本地/远程节点之间进行同步的消息传递 我认为使用move语义将stuff的数据移动到data应该会比复制数据给我带来巨大的性能提升,但在测试中,它在调试模式下的执行速度要慢得多,而在发布模式下的执行速度要慢得多。我在想,是否有一个标准的方法来实现最大的性能?以下是我使用的实现: std::vector<std::array<double, 5> > stu
数组
,让我们称它们为东西
,我想将所有这些对象合并成一个大的向量
,称之为数据
,用于在离散的本地/远程节点之间进行同步的消息传递
我认为使用move语义将stuff的数据移动到data应该会比复制数据给我带来巨大的性能提升,但在测试中,它在调试模式下的执行速度要慢得多,而在发布模式下的执行速度要慢得多。我在想,是否有一个标准的方法来实现最大的性能?以下是我使用的实现:
std::vector<std::array<double, 5> > stuff(2000);
std::vector<double> data;
data.reserve(10000);
(二)
(三)
(四)
附言:
我使用的g++的标志是
-O3-march=native-mavx
首先,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
来说,移动操作会更快,因为可以绕过数据的分配和深度拷贝,只需要一次分配。我们不会为size属性节省任何时间,因为它将被分配,就像在复制构造函数中一样。
对于不包含任何资源(如示例中的内存)的类型,move语义不会提高性能。所有属性都必须写入新位置,不管我们是否可以删除旧对象
在您的例子中,您尝试移动双
值,无论是否使用移动语义,这些值都必须复制到新位置。之所以会出现性能损失,可能是因为您阻止编译器对数据执行单个memcopy。执行一个memcopy操作通常比执行elementwise复制更快
最快的复制方式很可能是
std::memcpy
,其次是std::copy
,专门用于普通类型的std::memcpy
。您可能看不到速度的提高,因为编译器认识到,您希望复制大量的double并优化代码以使用memcpy。如果您想知道发生了什么,可以使用objdump或gdb检查asm代码。首先,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
来说,移动操作会更快,因为可以绕过数据的分配和深度拷贝,只需要一次分配。我们不会为size属性节省任何时间,因为它将被分配,就像在复制构造函数中一样。
对于不包含任何资源(如示例中的内存)的类型,move语义不会提高性能。所有属性都必须写入新位置,不管我们是否可以删除旧对象
在您的例子中,您尝试移动双
值,无论是否使用移动语义,这些值都必须复制到新位置。之所以会出现性能损失,可能是因为您阻止编译器对数据执行单个memcopy。执行一个memcopy操作通常比执行elementwise复制更快
最快的复制方式很可能是
std::memcpy
,其次是std::copy
,专门用于普通类型的std::memcpy
。您可能看不到速度的提高,因为编译器认识到,您希望复制大量的double并优化代码以使用memcpy。如果您想知道发生了什么,可以使用objdump或gdb检查asm代码。键入double
(和double
的std::array
)不会从std::move
中获益,它总是复制。如果您的std::array
是std::vector
,您可能会得到一些好处。最快的可能是用于(auto&b:stuff)数据
Typedouble
(和double
的std::array
)不能从std::move
中获益,它总是复制。如果您的std::array
是std::vector
,您可能会得到一些好处。最快的可能是用于(auto&b:stuff)数据代码>
for (auto & b : stuff) {
std::move(b.begin(), b.end(), std::back_inserter(data));
}
for (auto & b : stuff) {
for (const auto & item : b) {
data.emplace_back(item);
}
}
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);
}
...
};