You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Eigen Tensor:为何chip/slice求和与嵌套循环结果不一致?

Eigen Tensor中chip/slice求和与嵌套循环结果不一致的问题分析与解决

问题原因

  1. chip操作维度顺序错误:你当前的test_tensor.chip(1, m).chip(0, l)写法,会先固定原张量的第1维度(m),再固定新张量的第0维度(l),但由于Eigen Tensor在chip后维度顺序的变化,实际提取的子张量并非预期的test_tensor(l, m, :, :, :)。
  2. 手动求和方法错误:你的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 16:07:06