自定义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
相关产品推荐
相关产品推荐

