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

自定义Eigen表达式为何会分配临时内存?

排查Eigen自定义Padder表达式临时内存分配问题

你的Padder表达式触发临时内存分配主要有几个关键问题,逐个修复即可解决:

1. 缺失关键Flags标志

Eigen依赖表达式的Flags判断是否可直接求值、是否支持向量化等,你的traits中Flags设置不全,导致Eigen无法优化而分配临时内存。

修改internal::traits<Padder>中的enum部分:

enum {
    RowsAtCompileTime = AskedRows==Dynamic || RowPad == Dynamic || int(MatrixType::RowsAtCompileTime)==Dynamic
                      ? Dynamic
                      : AskedRows,
    ColsAtCompileTime = AskedCols==Dynamic || ColPad == Dynamic || int(MatrixType::ColsAtCompileTime)==Dynamic
                      ? Dynamic
                      : AskedCols,
    MaxRowsAtCompileTime = RowsAtCompileTime,
    MaxColsAtCompileTime = ColsAtCompileTime,
    // 明确设置是否为向量类型
    IsVectorAtCompileTime = (RowsAtCompileTime == 1 || ColsAtCompileTime == 1) ? 1 : 0,
    IsRowMajor = MaxRowsAtCompileTime==1 && MaxColsAtCompileTime!=1 ? 1
               : MaxColsAtCompileTime==1 && MaxRowsAtCompileTime!=1 ? 0
               : (MatrixType::Flags & RowMajorBit) ? 1 : 0,
    // 补充关键标志:继承原表达式的可遗传标志、支持向量化、无别名
    Flags = (traits<MatrixType>::Flags & (HereditaryBits | LvalueBit | PacketAccessBit)) 
            | (IsRowMajor ? RowMajorBit : 0) 
            | NoAliasBit | PacketAccessBit
};

2. Packet函数返回标量而非零数据包

你的packet函数中返回0.0是标量值,但Eigen期望返回对应PacketType的零数据包,这种类型不匹配会触发临时内存分配。

修改两个packet函数的返回语句,用pzero<PacketType>()替代0.0:

// 矩阵版本packet函数
template<int LoadMode, typename PacketType>
EIGEN_STRONG_INLINE
PacketType packet(Index row, Index col) const
{
    if (row < m_rowPad.value() || row >= m_rowPad.value() + m_rows.value())
        return pzero<PacketType>(); // 替换为零数据包
    if (col < m_colPad.value() || col >= m_colPad.value() + m_cols.value())
        return pzero<PacketType>(); // 替换为零数据包

    return m_argImpl.template packet<LoadMode,PacketType>(row - m_rowPad.value(), col - m_colPad.value());
}

// 向量版本packet函数
template<int LoadMode, typename PacketType>
EIGEN_STRONG_INLINE
PacketType packet(Index index) const
{
    Index actual_index;
    if (internal::traits<XprType>::RowsAtCompileTime==1) {
        if (index < m_rowPad.value() || index >= m_rowPad.value() + m_rows.value())
            return pzero<PacketType>(); // 替换为零数据包
        actual_index = index - m_rowPad.value();
    } else {
        if (index < m_colPad.value() || index >= m_colPad.value() + m_cols.value())
            return pzero<PacketType>(); // 替换为零数据包
        actual_index = index - m_colPad.value();
    }

    return m_argImpl.template packet<LoadMode,PacketType>(actual_index);
}

3. Evaluator Flags未包含PacketAccessBit

确保evaluator的Flags中包含PacketAccessBit,让Eigen知道该表达式支持向量化访问:

修改unary_evaluator中的enum部分:

enum {
    CoeffReadCost = evaluator<ArgTypeNestedCleaned>::CoeffReadCost,
    LinearAccessMask = XprType::IsVectorAtCompileTime ? LinearAccessBit : 0,
    Flags = (evaluator<ArgTypeNestedCleaned>::Flags & (HereditaryBits|LinearAccessMask|PacketAccessBit)) 
            | (traits<XprType>::Flags & (RowMajorBit|NoAliasBit))
            | PacketAccessBit,
    Alignment = evaluator<ArgTypeNestedCleaned>::Alignment
};

验证修复

启用代码中的MEMORY TEST部分:

Eigen::internal::set_is_malloc_allowed(false);
std::cout << pad(v2, 3, 3, 0, 0) << '\n';
std::cout << (v1 + pad(v2.segment (1, 2), 4, 1, 1, 0)).transpose() << '\n';
Eigen::internal::set_is_malloc_allowed(true);

编译运行后不会再触发内存分配错误。

内容的提问来源于stack exchange,提问作者Svalorzen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 08:40:54