Eigen:我应该使用对齐图进行密集计算吗?

问题描述 投票:1回答:1

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

我决定通过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;
}

我很确定这不是一个有效的基准,但是应该给我一些直觉。我用-march=native进行编译,并显示以下输出:

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
.......

因此在我看来,地图乘积和矩阵乘积之间没有太大区别。

我的问题是:1)Map<MatrixXf, Unaligned>Map<MatrixXf, Aligned>在性能方面有何区别?我是否应该关心Map对齐以进行点运算,逐元素加法等其他操作]

2)我的比较正确吗?

PS对不起,我的英语不好

c++ eigen matrix-multiplication memory-alignment eigen3
1个回答
2
投票

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

不同的数据对齐规范对性能有什么影响?为了回答这个问题,我们将讨论以下讨论:Talk: On a 32-bit architecture, would a 16-bit value not aligned on a 32-bit boundary be accessed more slowly?

  • 会影响性能的主要参数:将两个16位值打包到32位寄存器中,意味着您必须花费资源来将数据从一种格式转换为另一种格式

[有人可能会争辩说C / C ++之类的语言支持子词访问,这意味着您不必转换它们,这意味着您可以节省内存空间,并且对性能没有负面影响。

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

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

© www.soinside.com 2019 - 2024. All rights reserved.