提问人:Yes 提问时间:11/14/2023 更新时间:11/15/2023 访问量:43
是否可以根据数组中指定的值递归地对特征张量进行削片?
Is it possible to recursively chip an Eigen Tensor based on the values specified in an array?
问:
我正在尝试在 c++ 中围绕一个对象创建一个包装器。这个想法是基于提供的数组在张量上创建一个切片视图,该数组指定要切片的行或表示跳过此维度的切屑操作:Eigen::Tensor
-1
Eigen::Tensor<double, 3> tensor(4, 3, 2);
std::vector<int> indices = {3, -1, 1};
期望的结果与执行的结果相同
auto view = tensor.chip(1, 2).chip(3, 0)
获取最后一个维度中的第一行和第一个维度中的第三行。 (参见 Eigen::Tensor 文档中 chip 的文档)
我最初的方法是简单地使用一个循环:
template<typename T, int N>
auto createChippedAndSlicedView(Eigen::Tensor<T, N>& tensor, const Indices<N>& indices) {
auto view = tensor;
for (int i = N - 1; i >= 0; --i) {
if (indices.chip_indices[i] != -1) {
view = view.chip(indices.chip_indices[i], i);
}
}
return view;
}
但这行不通,因为我们正在改变我们试图在每次迭代中分配的维度,我们试图在尝试芯片的地方分配。然后,我尝试以递归方式实现它:view
#include <Eigen/Dense>
#include <unsupported/Eigen/CXX11/Tensor>
#include <iostream>
#include <vector>
template<typename TensorType>
auto chipTensorRecursive(TensorType &tensor, const std::vector<int> &indices, size_t dim) {
if (dim >= indices.size()) {
return tensor;
}
if (indices[dim] == -1) {
return chipTensorRecursive(tensor, indices, dim + 1);
} else {
auto chippedTensor = tensor.chip(indices[dim], dim);
return chipTensorRecursive(chippedTensor, indices, dim + 1);
}
}
template<typename TensorType>
auto chipTensor(TensorType &tensor, const std::vector<int> &indices) {
return chipTensorRecursive(tensor, indices, 0);
}
int main() {
Eigen::Tensor<double, 3> tensor(4, 3, 2);
std::vector<int> indices = {1, -1, 1};
tensor.setValues({{{ 0, 1}, { 2, 3}, { 4, 5}},
{{ 6, 7}, { 8, 9}, {10, 11}},
{{12, 13}, {14, 15}, {16, 17}},
{{18, 19}, {20, 21}, {22, 23}}});
auto result = chipTensor(tensor, indices);
std::cout << "Result: " << result << std::endl;
return 0;
}
但这会产生内部特征误差
In file included from /usr/include/eigen3/unsupported/Eigen/CXX11/Tensor:72,
from test.cpp:2:
/usr/include/eigen3/unsupported/Eigen/CXX11/src/Tensor/TensorInitializer.h: In instantiation of ‘struct Eigen::internal::Initializer<Eigen::TensorChippingOp<-1, Eigen::TensorChippingOp<-1, Eigen::TensorChippingOp<-1, Eigen::TensorChippingOp<-1, Eigen::Tensor<double, 3> > > > >, -893>’:
/usr/include/eigen3/unsupported/Eigen/CXX11/src/Tensor/TensorInitializer.h:29:53: recursively required from ‘struct Eigen::internal::Initializer<Eigen::TensorChippingOp<-1, Eigen::TensorChippingOp<-1, Eigen::TensorChippingOp<-1, Eigen::TensorChippingOp<-1, Eigen::Tensor<double, 3> > > > >, -2>’
/usr/include/eigen3/unsupported/Eigen/CXX11/src/Tensor/TensorInitializer.h:29:53: required from ‘struct Eigen::internal::Initializer<Eigen::TensorChippingOp<-1, Eigen::TensorChippingOp<-1, Eigen::TensorChippingOp<-1, Eigen::TensorChippingOp<-1, Eigen::Tensor<double, 3> > > > >, -1>’
/usr/include/eigen3/unsupported/Eigen/CXX11/src/Tensor/TensorBase.h:1006:34: required from ‘class Eigen::TensorBase<Eigen::TensorChippingOp<-1, Eigen::TensorChippingOp<-1, Eigen::TensorChippingOp<-1, Eigen::TensorChippingOp<-1, Eigen::Tensor<double, 3> > > > >, 1>’
/usr/include/eigen3/unsupported/Eigen/CXX11/src/Tensor/TensorChipping.h:80:7: required from ‘class Eigen::TensorChippingOp<-1, Eigen::TensorChippingOp<-1, Eigen::TensorChippingOp<-1, Eigen::TensorChippingOp<-1, Eigen::Tensor<double, 3> > > > >’
test.cpp:19:35: recursively required from ‘auto chipTensorRecursive(TensorType&, const std::vector<int>&, size_t) [with TensorType = Eigen::TensorChippingOp<-1, Eigen::Tensor<double, 3> >]’
test.cpp:19:35: required from ‘auto chipTensorRecursive(TensorType&, const std::vector<int>&, size_t) [with TensorType = Eigen::Tensor<double, 3>]’
test.cpp:25:31: required from ‘auto chipTensor(TensorType&, const std::vector<int>&) [with TensorType = Eigen::Tensor<double, 3>]’
test.cpp:42:29: required from here
/usr/include/eigen3/unsupported/Eigen/CXX11/src/Tensor/TensorInitializer.h:29:53: fatal error: template instantiation depth exceeds maximum of 900 (use ‘-ftemplate-depth=’ to increase the maximum)
29 | typename Initializer<Derived, N - 1>::InitList> InitList;
| ^~~~~~~~
compilation terminated.
声明它已达到可创建的模板的最大限制。根据我的理解,编译器应该尝试为每个维度创建一个模板方法的实例,直到指定的最大维度,在本例中为三个。为什么会创建这么多实例?
这是否被视为解决上述问题的干净方法?代码可以在此处的编译器资源管理器中运行chipTensorRecursive
答:
0赞
Yes
11/15/2023
#1
之所以出现这个问题,是因为在此实现中没有可靠地递减 N,这导致编译器为我们的 recursiveChip 函数创建无限多的实例。将输入数组减少到仅包含要进行芯片处理的维度,解决了该问题:
#include <Eigen/Dense>
#include <unsupported/Eigen/CXX11/Tensor>
#include <iostream>
#include <vector>
#include <utility>
template<typename TensorType, size_t N, size_t M=N>
auto chipTensorRecursive(TensorType &tensor, const std::array<std::pair<int, int>, N> &chips) {
if constexpr (M == 0) {
return tensor;
} else {
int dim = chips[M - 1].first; // Use N-1 as index
int row = chips[M - 1].second;
auto chippedTensor = tensor.chip(row, dim);
return chipTensorRecursive<decltype(chippedTensor), N, M-1>(chippedTensor, chips);
}
}
template<typename TensorType, size_t N>
auto chipTensor(TensorType &tensor, const std::array<std::pair<int, int>, N> &chips) {
return chipTensorRecursive<TensorType, N>(tensor, chips);
}
int main() {
Eigen::Tensor<double, 3> tensor(4, 3, 2);
std::array<std::pair<int, int>, 2> chips = {{{0, 1}, {2, 1}}};
tensor.setValues({{{0, 1}, {2, 3}, {4, 5}},
{{6, 7}, {8, 9}, {10, 11}},
{{12, 13}, {14, 15}, {16, 17}},
{{18, 19}, {20, 21}, {22, 23}}});
auto result = chipTensor(tensor, chips);
std::cout << "Result: " << result << std::endl;
return 0;
}
评论