【发布时间】:2015-03-10 16:09:53
【问题描述】:
我们正尝试在我的研究小组中实现一个新的 C++ 代码来执行大型数值模拟(有限元、有限差分法、拓扑优化等)。该软件将被学术界和工业界的人们使用。
对于软件的密集线性代数部分,我们想使用 Eigen 或 Armadillo。我们希望围绕这些包构建一个包装器,原因有两个: 1. 向用户公开我们自己的 API 而不是第三方 API; 2.以防我们将来需要切换库。我知道原因 2 是一种非常昂贵的保险形式,但是我们在使用之前的模拟软件时遇到了这种情况。
我遇到的关于包装第三方库的信息来自以下来源:
我的问题与构建这个包装类的最佳方法有关。理想情况下,薄层包装器是最好的,因为:
template< typename T >
class my_vec {
private:
arma::Col< T > _arma_vec;
};
或其等效的特征向量。
然后,我的类将调用第三方库类为:
my_vec::foo() { return _arma_vec.foo(); }
我认为(并且我想对此进行确认)这个薄层的问题是我失去了从这些库在引擎盖下实现的表达式模板获得的速度。例如,在犰狳中,以下操作:
// Assuming these vectors were already populated.
a = b + c + d;
变成这样:
for ( std::size_t i = 0; i < a.size(); ++i ) {
a[i] = b[i] + c[i] + d[i];
}
由于它们实现了expression templates 而没有创建任何临时对象。同样的情况也适用于 Eigen。
据我所知,我失去表达式模板功能的原因是,虽然 Armadillo 或 Eigen 不会创建自己的临时对象,但我的类 my_vec 会。避免这种情况的唯一方法是在其表达式模板周围构建一个薄层包装器。但是,在这一点上,这似乎违反了 YAGNI 原则。
这里有这个相关的问题:
建议使用类似的东西:
my_vec a, b, c;
// ... populate vectors
a._arma_vec = b._arma_vec + c._arma_vec;
是否可以使用类似的东西来代替?
template< typename T >
arma::Col< T > &
my_vec< T >::data() { return _arma_vec; }
a.data() = b.data() + c.data();
或者使用一些运算符重载来对用户隐藏 data() ? 如果我们不想直接使用这些库,还有哪些其他选择?使用宏?如果我们决定使用 C++11,使用别名?
或者构建这个包装类最方便的方法是什么?
【问题讨论】:
标签: c++ eigen armadillo expression-templates