【问题标题】:How to declare a tensor with Eigen without specifying the dimension?如何在不指定维度的情况下使用 Eigen 声明张量?
【发布时间】:2021-08-08 00:20:22
【问题描述】:

我有一个函数,它以 n 维张量作为输入,我必须存储这个张量以便以后重用。 但是,我事先不知道我的张量的维度。 我想这样做:

//in class.h
Eigen::Tensor<double, N> mytensor;
//in class.cpp 
mytensor = input; 

有没有办法做到这一点?

【问题讨论】:

  • 恐怕你用错了工具来完成这项工作。 N 只能在编译时指定。比我更了解 Eigen 的人可能会提供替代方案。
  • 嗯,我认为这也不可能,但对于 N 必须是 constexpr,所以编译器在编译时已经知道......对于有限数量的不同N 你可以使用std::varianthere

标签: c++ eigen tensor


【解决方案1】:

由于参数N是一个非类型模板参数,它必须是编译时已知的值。这意味着您不能真正将带有未指定 NEigen::Tensor 存储在变量中,因为每个具有不同大小的实例化都是不同的类型。

您可以使用std::variantstd::any 等容器解决此问题。它们可以分别存储来自封闭类型集或任何类型的类型的对象。例如,您可以使用 std::any 创建一个帮助程序 tensor_holder 类,如下所示:

template <typename T>
class tensor_holder
{
private:
    std::any _held;
    size_t _size;
public:
    template <int N>
    constexpr tensor_holder(Eigen::Tensor<T, N> tensor) :
        _held{std::move(tensor)},
        _size{N}
    {
    }
    constexpr tensor_holder(const tensor_holder&) = default;
    constexpr tensor_holder(tensor_holder&&) = default;
    template <size_t N>
    Eigen::Tensor<T, N>& get()
    {
        return std::any_cast<Eigen::Tensor<T, N>&>(_held);
    }
    template <size_t N>
    const Eigen::Tensor<T, N>& get() const
    {
        return std::any_cast<Eigen::Tensor<T, N>&>(_held);
    }
    constexpr int size() const noexcept
    {
        return _size;
    }
};

它将任意大小的Eigen::Tensor 存储在std::any 中。如果提供的大小不匹配,成员函数 get 将抛出 std::bad_any_cast 实际张量大小(请注意,大小作为编译时间值的限制不会消失)。

假设您有一小部分可能的张量大小,您可以像这样在函数中运行不同的分支:

void use_tensor(const tensor_holder<double>& in)
{
    static tensor_holder held = in; // it can be stored for later    

    if (held.size() == 4)
    {
        auto& tensor = held.get<4>();
        tensor(0, 1, 2, 3) = 115.5;
    }
    else if (held.size() == 3)
    {
        // some other logic
    }
}

在这种情况下,您也可以使用 switch 而不是 if。仅当您必须支持的不同张量大小的数量很少时,此解决方案才实用。我不知道你打算如何使用你的张量,所以我很难说这个解决方案是否足够。

感谢 tensor_holder 类的转换构造函数,您可以通过简单地提供任意大小的 Eigen::Tensor 来调用该函数:

use_tensor(Eigen::Tensor<double, 3>{});

(godbolt)

【讨论】:

    猜你喜欢
    • 2018-03-26
    • 2021-11-12
    • 2017-03-30
    • 1970-01-01
    • 2017-06-24
    • 2017-07-18
    • 1970-01-01
    • 2017-12-19
    • 2021-11-30
    相关资源
    最近更新 更多