经过一些转置后,Eigen::Tensor contraction 会更快吗?比如提前将所有合约指数按特定顺序排列?

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

我有两个 Eigen::Tensor 数组,A,B。每个数组中的张量具有相同的等级。在我的程序中,我将根据一些规则(该规则将保证维度匹配)在 A 数组中收缩一个张量,在 B 数组中收缩一个张量。并且收缩指数相同。我会这样做很多次。例如,A 中的张量具有等级 3,B 中的张量具有等级 4,我想在数组 A 中的张量中的索引 0,2 和数组 B 中的张量中的索引 1,2 之间收缩。

所以我想知道首先对它们进行排列是否会更好,因为我知道张量收缩主要是通过首先重塑矩阵然后进行矩阵乘法来实现的。

我尝试了一个如下的小例子,但结果不是我预期的,因为执行时间是相似的。

#include <unsupported/Eigen/CXX11/Tensor>
#include <Eigen/Dense>
#include <chrono>
#include <iostream>
#include <iomanip>
typedef std::complex<double> cplx;

int main()
{
    std::chrono::time_point<std::chrono::high_resolution_clock> t0,t1;
    Eigen::Tensor<cplx,3> a(200,100,90);
    a.setRandom();
    Eigen::Tensor<cplx,3> b(200,50,100);
    b.setRandom();
    t0= std::chrono::high_resolution_clock::now();

    Eigen::array<Eigen::IndexPair<int>, 1> product_dims = {Eigen::IndexPair<int>(0,0)};
    for(int i=0;i<10;++i)
        Eigen::Tensor<cplx,4> c=a.contract(b,product_dims);
    t1= std::chrono::high_resolution_clock::now();
    std::cout<<std::setprecision(12)<<" in time: "<<1*1e-10*(double)std::chrono::duration_cast<std::chrono::nanoseconds>(t1-t0).count()<<"s"<<std::endl;

    Eigen::Tensor<cplx,3> dd=a.shuffle(std::vector{1,2,0});
    Eigen::Tensor<cplx,3> ee=b.shuffle(std::vector{1,2,0});

    t0= std::chrono::high_resolution_clock::now();
    product_dims = {Eigen::IndexPair<int>(2,2)};
    for(int i=0;i<10;++i)
        Eigen::Tensor<cplx,4> c=dd.contract(ee,product_dims);
    t1= std::chrono::high_resolution_clock::now();
    std::cout<<std::setprecision(12)<<" in time: "<<1*1e-10*(double)std::chrono::duration_cast<std::chrono::nanoseconds>(t1-t0).count()<<"s"<<std::endl;

    t0= std::chrono::high_resolution_clock::now();
    product_dims = {Eigen::IndexPair<int>(2,0)};
    for(int i=0;i<10;++i)
         Eigen::Tensor<cplx,4> c=dd.contract(b,product_dims);
    t1= std::chrono::high_resolution_clock::now();
    std::cout<<std::setprecision(12)<<" in time: "<<1*1e-10*(double)std::chrono::duration_cast<std::chrono::nanoseconds>(t1-t0).count()<<"s"<<std::endl;

    t0= std::chrono::high_resolution_clock::now();
    product_dims = {Eigen::IndexPair<int>(0,2)};
    for(int i=0;i<10;++i)
        Eigen::Tensor<cplx,4> c=a.contract(ee,product_dims);
    t1= std::chrono::high_resolution_clock::now();
    std::cout<<std::setprecision(12)<<" in time: "<<1*1e-10*(double)std::chrono::duration_cast<std::chrono::nanoseconds>(t1-t0).count()<<"s"<<std::endl;

}

我正在 mac os 上测试,编译命令是 -O3 -march=native -std=c++17。现在的时间是 : 及时:2.4562778s 及时:2.4876118s 及时:2.4699632s 及时:2.4621803s

c++ eigen tensor
© www.soinside.com 2019 - 2024. All rights reserved.