Eigen Tensor:为何chip/slice求和与嵌套循环结果不一致?
Eigen Tensor中chip/slice求和与嵌套循环结果不一致的问题分析与解决
问题原因
- chip操作维度顺序错误:你当前的
test_tensor.chip(1, m).chip(0, l)写法,会先固定原张量的第1维度(m),再固定新张量的第0维度(l),但由于Eigen Tensor在chip后维度顺序的变化,实际提取的子张量并非预期的test_tensor(l, m, :, :, :)。 - 手动求和方法错误:你的
tensor_sum函数直接通过data()遍历元素,仅适用于连续存储的完整张量。而chip/slice返回的是视图对象,元素在原始存储中是非连续的,直接访问data()会拿到错误的元素顺序,导致求和结果偏差。
解决方案
方法1:修正chip顺序并使用Eigen内置求和函数
Eigen Tensor模块提供了sum()方法,可直接对张量/视图按逻辑顺序求和,避免手动遍历的错误。
#include <unsupported/Eigen/CXX11/Tensor> #include <Eigen/Core> #include <iostream> int main() { Eigen::Tensor<double, 5> test_tensor(3,3,2,1,1); test_tensor.setValues({ {{{{1.1}},{{1.1}}},{{{0}},{{0}}},{{{0}},{{0}}}}, {{{{0}}, {{0}}}, {{{1}},{{1}}},{{{0}},{{0}}}}, {{{{0}}, {{0}}}, {{{0}},{{0}}},{{{1}},{{1}}}} }); // 修正chip顺序+内置sum求和 for (int l = 0; l < 3; ++l) { for (int m = 0; m < 3; ++m) { // 先固定原张量第0维(l),再固定新张量第0维(m),得到目标3维子张量 auto subtensor = test_tensor.chip(0, l).chip(0, m); double sum = subtensor.sum(); std::cout << "sum chip " << l << " " << m << " " << sum << std::endl; } } // 嵌套循环对照 double sum; for (int l = 0; l < 3; ++l) { for (int m = 0; m < 3; ++m) { sum = 0; for (int i = 0; i < 2; ++i) { for (int j = 0; j < 1; ++j) { for (int k = 0; k < 1; ++k) { sum += test_tensor(l, m, i, j, k); } } } std::cout << "sum nested loops " << l << " " << m << " " << sum << std::endl; } } return 0; }
方法2:直接使用slice提取子张量
若偏好slice操作,可直接指定5维张量的起始索引和大小,再调用sum()求和:
// 替换chip求和部分的代码 for (int l = 0; l < 3; ++l) { for (int m = 0; m < 3; ++m) { Eigen::array<Eigen::Index, 5> start = {l, m, 0, 0, 0}; Eigen::array<Eigen::Index, 5> size = {1, 1, 2, 1, 1}; auto subtensor = test_tensor.slice(start, size); double sum = subtensor.sum(); std::cout << "sum slice " << l << " " << m << " " << sum << std::endl; } }
关键注意事项
- 禁止直接遍历
data():Tensor视图的元素存储是非连续的,data()指向原始张量的底层存储,直接遍历会破坏逻辑顺序,必须使用Eigen内置的聚合函数(如sum()、mean())处理。 - chip操作的维度逻辑:每次调用
chip(dim, index)后,返回的张量会移除指定维度,剩余维度保持原顺序。提取多维固定索引时,需从左到右依次固定原始张量的维度(先固定第0维,再固定新张量的第0维)。
内容的提问来源于stack exchange,提问作者Yes
相关产品推荐
相关产品推荐

