我一直在为一个新项目测试 Eigen3 的 Tensor 模块。 即使模块尚未完成,它似乎也具有我需要的大部分功能。
但是有一部分我不太明白。每当我有一个大张量并且我想从中提取一个切片时,Eigen 就会复制数据。
有没有办法不复制数据,而是指向切片中的原始数据块?
例如,如果我这样做:
Tensor<float, 3> A(100,1000,1000); A.setZero();
Eigen::array<int, 3> offsets = {0, 0, 0};
Eigen::array<int, 3> extents = {2, 2, 2};
Tensor<float, 3> c = A.slice(offsets, extents);
A(0,0,0) = 1.0;
cerr << c << endl;
但是“c”的第一个元素仍然为零,而不是映射到修改后的“A(0,0,0)”数据块。
您可以使用 TensorMap 基于切片的共享内存空间创建张量。然而,只有当您的切片占据数据数组的连续部分时,这才有效。否则,您将需要进行一些张量算术来计算出单个切片各个部分的开始和结束 1d 索引。
TensorMap<Tensor<float, 3, RowMajor> > row_major(data, ...);
现在,这是开箱即用的:
using Eigen::Tensor;
Tensor<float, 3> img(4, 4, 3);
img.setConstant(1);
img.slice(array<int, 3>{0, 0, 0}, array<int, 3>{2, 2, 3}).setZero();
Tensor<float, 3> patch(2, 2, 3);
patch.setRandom();
img.slice(array<int, 3>{2, 2, 0}, array<int, 3>{2, 2, 3}) = patch;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
std::cout << "(";
for (int c = 0; c < 3; c++) {
std::cout << img(i, j, c) << ", ";
}
std::cout << ") ";
}
std::cout << std::endl;
}
(0, 0, 0, ) (0, 0, 0, ) (1, 1, 1, ) (1, 1, 1, )
(0, 0, 0, ) (0, 0, 0, ) (1, 1, 1, ) (1, 1, 1, )
(1, 1, 1, ) (1, 1, 1, ) (0.00576293, 0.909376, 0.049831, ) (0.168537, 0.634598, 0.603522, )
(1, 1, 1, ) (1, 1, 1, ) (0.288325, 0.286939, 0.183521, ) (0.808391, 0.085356, 0.00413311, )