Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/158.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++ 艾根:我应该使用对齐地图进行密集计算吗?_C++_Eigen_Matrix Multiplication_Memory Alignment_Eigen3 - Fatal编程技术网

C++ 艾根:我应该使用对齐地图进行密集计算吗?

C++ 艾根:我应该使用对齐地图进行密集计算吗?,c++,eigen,matrix-multiplication,memory-alignment,eigen3,C++,Eigen,Matrix Multiplication,Memory Alignment,Eigen3,我想对外部分配的数据执行大量计算,尤其是矩阵乘法。可以通过Eigen::Map完成。不幸的是,我不是矢量化计算方面的专家,但据我所知,可以为Map指定Aligned标志 我决定通过Eigen::MatrixXf和'Eigen::Map'检查矩阵乘法之间的性能差异: void testMatProduct( const Eigen::MatrixXf &a, const Eigen::MatrixXf &b, Eigen::Matri

我想对外部分配的数据执行大量计算,尤其是矩阵乘法。可以通过
Eigen::Map
完成。不幸的是,我不是矢量化计算方面的专家,但据我所知,可以为
Map
指定
Aligned
标志

我决定通过
Eigen::MatrixXf
和'Eigen::Map'检查矩阵乘法之间的性能差异:

void testMatProduct(
        const Eigen::MatrixXf &a,
        const Eigen::MatrixXf &b,
        Eigen::MatrixXf &res)
{
    const auto startTime = std::chrono::high_resolution_clock::now();
    res.noalias() = a * b;
    const auto endTime = std::chrono::high_resolution_clock::now();
    const auto duration = std::chrono::duration_cast<std::chrono::microseconds>( endTime - startTime ).count();
    std::cout << "Mat product elapsed " << duration / 1.0e6 << std::endl;
}

using EigenMap = Eigen::Map<Eigen::MatrixXf, Eigen::Unaligned>;

void testMapProduct(
        const EigenMap &a,
        const EigenMap &b,
        EigenMap &res)
{
    const auto startTime = std::chrono::high_resolution_clock::now();
    res.noalias() = a * b;
    const auto endTime = std::chrono::high_resolution_clock::now();
    const auto duration = std::chrono::duration_cast<std::chrono::microseconds>( endTime - startTime ).count();
    std::cout << "Map product elapsed " << duration / 1.0e6 << std::endl;
}

int main(int, char **)
{    
    srand(42);
    const int64_t N = 7000;
    const int64_t K = 6000;
    const int64_t M = 100;
    Eigen::MatrixXf mat1 = Eigen::MatrixXf::Random(N, K);
    Eigen::MatrixXf mat2 = Eigen::MatrixXf::Random(K, M);
    Eigen::MatrixXf matRes = Eigen::MatrixXf::Zero(N, M);

    // Copy data from mats to vecs
    Eigen::VectorXf vec1 = Eigen::Map<Eigen::MatrixXf>(mat1.data(), mat1.rows() * mat1.cols(), 1);
    Eigen::VectorXf vec2 = Eigen::Map<Eigen::MatrixXf>(mat2.data(), mat2.rows() * mat2.cols(), 1);
    Eigen::VectorXf vecRes = Eigen::VectorXf::Zero(N * M);

    EigenMap map1 = EigenMap(vec1.data(), mat1.rows(), mat1.cols());
    EigenMap map2 = EigenMap(vec2.data(), mat2.rows(), mat2.cols());
    EigenMap mapRes = EigenMap(vecRes.data(), matRes.rows(), matRes.cols());
    for(int i = 0; i < 10; ++i){
        testMapProduct(map1, map2, mapRes);
        testMatProduct(mat1, mat2, matRes);
        matRes.setZero();
        vecRes.setZero();
    }

    return 0;
}
所以在我看来,映射积和矩阵积之间并没有太大的区别

我的问题是: 1)
Map
Map
在性能方面有什么区别?我是否应该关心点积、元素添加等其他操作的
Map
对齐

2) 我的比较正确吗

PS对不起,我的英语很差。

1)数据对齐指定了访问和排列数据的方式。这意味着如果您使用的是
Eigen::MatrixXf
,它是指编译时数据类型为
float
的未知维度矩阵,那么数据指针应该在4字节(32位)边界上对齐(假设系统上使用32位表示float)

不同的数据对齐规范对性能有什么影响?为了回答这个问题,我们将看下面的讨论:

  • 影响性能的主要论点:将两个16位值打包到32位寄存器意味着您必须花费资源将数据从一种格式转换为另一种格式
有人可能会认为,C/C++等语言支持子字访问,这意味着您不必转换它们,这意味着您可以节省内存空间,并且不会对性能产生负面影响

我假设Eigen库自动检测到
Eigen::MatrixXf
的数据指针在4字节边界上对齐,因此如果您省略
MapOption
模板或将其分配给
Eigen::Unaligned
,则不会影响性能。如果您想确保使用
Eigen::Aligned4
(回想一下
Eigen::Aligned
不推荐的,是
Aligned16
的同义词,所以是128位)。您可以查看对齐枚举器


2)
Eigen::Map
Eigen::Matrix
Eigen::Vector
不同,它的优点是可以在不复制数据的情况下初始化矩阵和向量。我很确定
Eigen::Map
Eigen::Matrix
使用相同的操作进行乘法、加法等。下面的对象,只是引用不同。使用
Eigen::Matrix
可以看到的唯一性能优势是空间局部性在缓存性能方面,如果
Eigen::Map
引用了内存中相距很远的两个矩阵/向量,并且使用了巨大的矩阵大小。当然,假设您刚刚初始化了两个
Eigen::Matrix
对象,以便它们在内存中是连续的。

主要区别在于矢量化的加载是对齐的加载还是未对齐的加载(或者跨越缓存线边界时)。在现代桌面CPU(例如,任何带有AVX、IIRC的CPU)上,差异将很小,与实际工作相比,差异将很小。在其他设备上,不对齐负载的惩罚可能会有很大差异

如果
Eigen::Map
保证内存对齐,则所有负载都可以是对齐的负载,而如果不保证,则所有负载都必须是未对齐的负载。这对应用程序的影响程度取决于您的目标硬件

Map product elapsed 0.102751
Mat product elapsed 0.10224
Map product elapsed 0.10022
Mat product elapsed 0.100726
Map product elapsed 0.09963
Mat product elapsed 0.100697
Map product elapsed 0.099673
Mat product elapsed 0.100809
Map product elapsed 0.100195
.......