本征:累积可变大小的数组 [英] Eigen: Accumulating arrays of variable size
问题描述
我有一个保存数据Eigen :: Array的类,以及一个通过沿第一个轴附加到数组中来添加新数据(行数可能会变化)的方法.我通过创建一个合适大小的新Array并使用旧数据和新数据初始化它来解决累积问题.
I have a class holding an Eigen::Array of data and a method that adds new data (number of rows may vary) by appending to the array along the first axis. I solved the accumulation by creating a new Array of the right size and initializing it with the old and the new data.
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_;
}
这样做有什么问题吗?还是最好调整累积数据数组的大小:
Is there anything wrong with doing it like this? Or is it preferred to resize the accumulated data array:
-
.resize()
并同时复制新旧 - 或
.conservative_resize()
并复制新数据(如果新数据长于1行,则需要执行块操作)
.resize()
and copy in both old and new- or
.conservative_resize()
and copy in the new data (requires block operations if new data is longer than 1 row)
推荐答案
首先,您当前的实现存在两个易于修复的缺陷:
First of all, two easy-to-fix flaws with your current implementation:
-
Eigen默认情况下按列主顺序存储数组(和矩阵),因此,如果要追加行,则应首选
RowMajor
存储顺序:
Eigen :: Array< double,Eigen :: Dynamic,3,Eigen :: RowMajor>
由于将不再使用 accu
,因此应将其移至累加器: accumulated_data_ = std :: move(accu);
Since accu
will not be used anymore, you should move it to the accumulator:
accumulated_data_ = std::move(accu);
如果您使用的是C ++ 11之前的版本,则还可以交换数据:
If you are pre-C++11, you can also swap the data:
accumulated_data_.swap(accu);
那么您的方法几乎等同于
Then your approach is nearly equivalent to
accumulated_data_.conservativeResize(accumulated_data_.rows() + new_data.rows(), 3);
accumulated_data_.bottomRows(new_data.rows()) = new_data;
在每次调用时,您仍将具有内存(重新)分配和内存副本.
You will still have memory (re-)allocations and memory-copies at every call.
一种更有效的方法是仅偶尔(理想情况下仅在开始时一次)调整 accumulated_data _
的大小,并跟踪其中当前实际有效的数量:
A more efficient approach would be to resize the accumulated_data_
only occasionally (ideally just once at the beginning), and keep track of how much of it is currently actually valid:
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_;
};
这篇关于本征:累积可变大小的数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!