本征:累积可变大小的数组
Eigen: Accumulating arrays of variable size
我有一个 class 保存 Eigen::Array 数据和一种通过沿第一个轴附加到数组来添加新数据(行数可能会有所不同)的方法。我通过创建一个大小合适的新数组并用新旧数据对其进行初始化来解决累积问题。
typedef Eigen::Array<double, Eigen::Dynamic, 3> DataArray
class Accumulator {
void add(DataArray &new_data) {
DataArray accu(accumulated_data_.rows() + new_data.rows(), 3)
accu << accumulated_data_, new_data;
accumulated_data_ = accu;
}
DataArray accumulated_data_;
}
这样做有什么问题吗?或者更喜欢调整累积数据数组的大小:
.resize()
并复制旧版和新版
- 或
.conservative_resize()
并复制新数据(如果新数据超过1行,则需要块操作)
首先,您当前的实现存在两个易于修复的缺陷:
Eigen 默认以列优先顺序存储数组(和矩阵),因此如果要追加行,您应该更喜欢 RowMajor
存储顺序:
Eigen::Array<double, Eigen::Dynamic, 3, Eigen::RowMajor>
由于accu
不会再被使用,所以应该将其移动到累加器中:
accumulated_data_ = std::move(accu);
如果你是pre-C++11,你也可以交换数据:
accumulated_data_.swap(accu);
那么你的方法几乎等同于
accumulated_data_.conservativeResize(accumulated_data_.rows() + new_data.rows(), 3);
accumulated_data_.bottomRows(new_data.rows()) = new_data;
您仍然会在每次调用时进行内存(重新)分配和内存复制。
一种更有效的方法是偶尔调整 accumulated_data_
的大小(最好只在开始时调整一次),并跟踪其中有多少当前实际有效:
typedef Eigen::Array<double, Eigen::Dynamic, 3, Eigen::RowMajor> DataArray;
class Accumulator {
public:
Accumulator(Eigen::Index initialCapacity=10000) : accumulated_data_(initialCapacity, 3), actual_rows_(0) {}
void add(DataArray &new_data) {
if(actual_rows_+new_data.rows() > accumulated_data_.rows())
{ // TODO adapt memory-growing to your use case
accumulated_data_.conservativeResize(2*actual_rows_+new_data.rows(), 3);
}
accumulated_data_.midRows(actual_rows, new_data.rows()) = new_data;
actual_rows_+=new_data.rows();
}
DataArray accumulated_data_;
Eigen::Index actual_rows_;
};
我有一个 class 保存 Eigen::Array 数据和一种通过沿第一个轴附加到数组来添加新数据(行数可能会有所不同)的方法。我通过创建一个大小合适的新数组并用新旧数据对其进行初始化来解决累积问题。
typedef Eigen::Array<double, Eigen::Dynamic, 3> DataArray
class Accumulator {
void add(DataArray &new_data) {
DataArray accu(accumulated_data_.rows() + new_data.rows(), 3)
accu << accumulated_data_, new_data;
accumulated_data_ = accu;
}
DataArray accumulated_data_;
}
这样做有什么问题吗?或者更喜欢调整累积数据数组的大小:
.resize()
并复制旧版和新版- 或
.conservative_resize()
并复制新数据(如果新数据超过1行,则需要块操作)
首先,您当前的实现存在两个易于修复的缺陷:
Eigen 默认以列优先顺序存储数组(和矩阵),因此如果要追加行,您应该更喜欢
RowMajor
存储顺序:Eigen::Array<double, Eigen::Dynamic, 3, Eigen::RowMajor>
由于
accu
不会再被使用,所以应该将其移动到累加器中:accumulated_data_ = std::move(accu);
如果你是pre-C++11,你也可以交换数据:
accumulated_data_.swap(accu);
那么你的方法几乎等同于
accumulated_data_.conservativeResize(accumulated_data_.rows() + new_data.rows(), 3);
accumulated_data_.bottomRows(new_data.rows()) = new_data;
您仍然会在每次调用时进行内存(重新)分配和内存复制。
一种更有效的方法是偶尔调整 accumulated_data_
的大小(最好只在开始时调整一次),并跟踪其中有多少当前实际有效:
typedef Eigen::Array<double, Eigen::Dynamic, 3, Eigen::RowMajor> DataArray;
class Accumulator {
public:
Accumulator(Eigen::Index initialCapacity=10000) : accumulated_data_(initialCapacity, 3), actual_rows_(0) {}
void add(DataArray &new_data) {
if(actual_rows_+new_data.rows() > accumulated_data_.rows())
{ // TODO adapt memory-growing to your use case
accumulated_data_.conservativeResize(2*actual_rows_+new_data.rows(), 3);
}
accumulated_data_.midRows(actual_rows, new_data.rows()) = new_data;
actual_rows_+=new_data.rows();
}
DataArray accumulated_data_;
Eigen::Index actual_rows_;
};