Eigen中的混叠(aliasing)问题
Eigen中的混疊(aliasing)問題
Eigen中aliasing指的是在賦值表達式的左右兩邊存在矩陣的重疊區域,這種情況下,有可能得到非預期的結果。如mat = 2*mat或者mat = mat.transpose(),第一個例子中的alias是沒有問題的,而第二的例子則會導致非預期的計算結果。
下面例子:
MatrixXi mat(3,3); mat << 1, 2, 3, 4, 5, 6, 7, 8, 9; cout << "Here is the matrix mat:\n" << mat << endl; // This assignment shows the aliasing problem mat.bottomRightCorner(2,2) = mat.topLeftCorner(2,2); cout << "After the assignment, mat = \n" << mat << endl;結果:
Here is the matrix mat: 1 2 3 4 5 6 7 8 9 After the assignment, mat = 1 2 3 4 1 2 7 4 1上述結果中,最后一個元素并不是所希望的5,而是1,造成這個問題的原因:eigen中賦值操作采用了延遲計算(也稱惰性計算(Lazy Evaluation))的方式,簡單說就是當賦值運算并不會馬上執行計算,而是在需要用到該變量時才進行計算,可以將上述運算等價成如下過程:
mat(1,1) = mat(0,0); mat(1,2) = mat(0,1); mat(2,1) = mat(1,0); mat(2,2) = mat(1,1);混疊在編譯器是無法識別的,但在運行期(debug模式下)會有異常提示,可以通過 EIGEN_NO_DEBUG關閉這個異常提示,但最好不要。注:release模式下不會提示。
解決混疊問題:
最直接的方法就是避免混疊,可通過臨時變量進行賦值,也可通過eigen提供的eval()操作,該操作的作用是立即評估該表達式。
MatrixXi mat(3,3); mat << 1, 2, 3, 4, 5, 6, 7, 8, 9; // 臨時變量: Matrix2d tmp = mat.topLeftCorner(2,2); mat.bottomRightCorner(2,2) = tmp; // 或者 mat.bottomRightCorner(2,2) = mat.topLeftCorner(2,2).eval();此外,eigen中對于某些特殊的操作,為了避免這個問題,提供了對應版本的函數:比如transpose(),可直接用其另外一個函數:transposeInPlace(),這些操作包括:
此外:可用conservativeResize()代替如 mat = mat.topLeftCorner(2,2).eval() 這樣的操作。
不一定所有存在混疊的表達式都會出現問題:
很顯然,如果計算式只對每個元素進行獨立操作,即便表達式左右兩邊存在混疊的情況,也不會有問題,比如:
MatrixXf mat(2,2); mat << 1, 2, 4, 7; mat = 2 * mat; mat = mat - MatrixXf::Identity(2,2);上述計算都能正常進行。此外,對于矩陣相乘操作,因為Eigen默認進行了混疊處理,所以也可以直接賦值,而不會產生意外結果:
MatrixXf matA(2,2); matA << 2, 0, 0, 2;matA = matA * matA // 正確matA = matA * matA表達式中,eigen在內部將矩陣相乘直接的結果直接賦值給一個臨時變量,從而避免了混疊的影響,但對于如:matB = matA * matA也進行同樣的操作,顯然會影響效率(先賦值給臨時變量,然后由臨時變量在賦值給目標變量),可通過noalias(), 避免這個問題:matB.noalias() = matA * matA;
總結:
參考資料:
http://eigen.tuxfamily.org/dox/group__TopicAliasing.html
總結
以上是生活随笔為你收集整理的Eigen中的混叠(aliasing)问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python悬浮可移动置顶计时软件Att
- 下一篇: RDM (研发管理)