我正在为一个特殊的应用程序调整霍夫变换,为此,我需要在一个向量中存储大量的特征矩阵,并且我需要它们一开始都为0。这就是我初始化这个的方式:
typedef Eigen::Matrix<int,30,150> HoughMatrix
std::vector<HoughMatrix> hough_spaces(num_spaces)
我现在的问题是,让所有矩阵的所有元素都等于0的最快方法是什么?我试着在每个Vector元素上循环,然后做:
hough_spaces[i].setZero()
但这相当缓慢。有更快的路吗?或者直接将它们初始化为0的方法?感谢您的帮助
首先,默认情况下,Eigen::Matrix<int,30,150>
将与16个字节对齐,这在64位系统或C++17中很可能正常工作,但您可能会面临一些警告。解决对齐问题的一个简单方法是编写
typedef Eigen::Matrix<int,30,150, Eigen::DontAlign> HoughMatrix;
现在,写你想要的东西的惯用方法是写
std::vector<HoughMatrix> hough_spaces(num_spaces, HoughMatrix::Zero());
然而,这将导致memcpy
调用的循环(至少对于gcc和clang:https://godbolt.org/z/ULixBm)。
或者,您可以创建一个未初始化的HoughMatrix
es的向量,并在它们上应用std::memset
:
std::vector<HoughMatrix> hough_spaces(num_spaces);
std::memset(hough_spaces.data(), 0, num_spaces*sizeof(HoughMatrix));
注意,为了在没有Eigen必须循环通过所有元素的情况下运行,需要使HoughMatrix
不对齐(如开头所示(或禁用对齐断言:https://godbolt.org/z/nDJqV5
如果您实际上不需要std::vector
功能(主要是复制和调整大小的功能(,您可以在使用后使用calloc
和free
来分配一些内存。为了防止泄漏,可以将其封装到std::unique_ptr
:中
// unique_ptr with custom deallocator (use a typedef, if you need this more often):
std::unique_ptr<HoughMatrix[], void(&)(void*)> hough_spaces(static_cast<HoughMatrix*>(std::calloc(num_spaces, sizeof(HoughMatrix))), std::free);
if(!hough_spaces) throw std::bad_alloc(); // Useful, if you actually handle bad-allocs. If you ignore failed callocs, you'll likely segfault when accessing the data.
Clang和gcc将其优化为单个calloc
/free
对:https://godbolt.org/z/m4rzRq
一种完全不同的方法是尝试使用3D张量而不是矩阵向量:
typedef Eigen::Tensor<int, 3> HoughSpace;
HoughSpace hough_spaces(num_spaces,30,150);
hough_spaces.setZero();
从生成的程序集来看,即使使用-O3 -DNDEBUG
,这看起来也是半最优的。
总的来说,请注意,对任何与内存相关的东西进行基准测试都可能会产生误导。例如,对calloc
的调用可以几乎即时地但在较低级别上返回到未分配的页面,这使得第一次实际访问它们的成本更高。
有趣的是,Eigen::Matrix
似乎没有用于初始化元素的构造函数。来自特征:矩阵类:
Matrix3f a;
->没有分配,没有初始化元素
MatrixXf a(10,15);
->已分配但未初始化的元素
最后(!(一些允许初始化小型矢量元素的构造函数:
Vector2d a(5.0, 6.0); Vector3d b(5.0, 6.0, 7.0); Vector4d c(5.0, 6.0, 7.0, 8.0);
如果您继续阅读特征:高级初始化,您可以找到
特殊矩阵和数组
Matrix和Array类具有类似Zero((的静态方法可以用于将所有系数初始化为零。[…]
示例
std::cout << "A fixed-size array:n"; Array33f a1 = Array33f::Zero(); std::cout << a1 << "nn";
PS
但这相当缓慢。有更快的路吗?
如果不知道"慢"是什么意思的更多细节,就很难讨论细节。我所能说的是,我希望初始化只比分配单元化元素和setZero()
更快。