Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/164.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用move::semantic将大量向量合并为更大的向量_C++_C++11_Vector_C++14_Move - Fatal编程技术网

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)数据
Type
double
(和
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);
    }
    ...        
};