2016-12-11 73 views
2

它看起來像使用特徵類型與STL容器非常混亂,需要特別注意對齊問題。我的問題是,我打算創建複雜的類層次結構,其中可能包含一個或多個Eigen類型作爲成員變量的幾十個類。從文檔看來,只要在成員變量中包含Eigen類型,您的類就會受到與「特徵」類型相同的問題「感染」。這意味着我必須格外小心使用STL容器,不僅適用於Eigen類型,而且適用於我所有的幾十個類。使用特徵類型與STL容器和std :: vector

更讓我擔心的是,任何在我們的代碼中使用我的類的實例的人都會遇到同樣的問題,並且需要成爲這個主題的專家 - 即使我的類沒有公開任何特徵類型他們的公共接口!

這很令人沮喪。我有問題,

  1. 我的理解上面是否正確(我只需要支持C++ 11和現代編譯器)?
  2. 是否有任何模式的人使用,所以他們不必污染他們的代碼與特殊的Eigen處理各地?
  3. 我在想全局禁用整個矢量化。這是否會以犧牲性能爲代價來解決上述問題?只有特定的代碼纔可以選擇啓用它嗎?
  4. 如果我忘記在代碼的某個地方照顧對齊問題,我是否總是遇到編譯時錯誤,或者問題可能會保持隱藏狀態,並且在運行時可能會崩潰?

回答

4

是你的理解大多是正確的,但我要補充一點,這僅涉及本徵的需要對齊固定大小類型,如Vector4fMatrix2d等,但不Vector3fMatrixXd。而且,問題的核心在於STL容器並不符合alignas的要求,儘管這應該會在未來的C++版本中出現。

我認爲要避免這種困境的最簡單的方法是使用非對齊徵的類型類成員和容器的價值類型,如:

typedef Eigen::Matrix<float,4,1,Eigen::DontAlign> UVector4f; 
typedef Eigen::Matrix<double,2,2,Eigen::DontAlign> UMatrix2d; 

這樣你就不必操心對齊問題,而且你不會鬆散明確的矢量化。在特徵3.3中,未對齊的對象也是矢量化的。

編輯:

關於你的最後一個問題,遺憾的是,在C++中沒有可能在編譯時檢測到這樣的缺點。如果斷言未被禁用,並且在運行時發生無效的未對齊分配,那麼您將獲得明確的斷言消息,但這就是我們所能做的。因此,如果您的程序在給定編譯標誌的給定系統上運行良好,那麼這並不意味着您的代碼是安全的。例如,在大多數64位系統緩衝區都對齊在16字節的邊界上,所以,如果你不啓用AVX指令集,那麼你的代碼將運行良好。另一方面,如果移動到更奇特的平臺,或者啓用默認需要32字節對齊的AVX指令,相同的代碼可能會斷言。儘管如此,靜態分析儀正在變得越來越強大,我認爲這些問題可以被他們發現。

另一種策略是用自定義的malloc檢查程序,只返回8個字節對齊的緩衝區。這樣你就可以捕捉到所有的缺點,假設你的程序已經被單元測試覆蓋了。爲此,您必須編譯爲-DEIGEN_MALLOC_ALREADY_ALIGNED=0,原因很明顯。

+1

快速提問:如果我忘記在代碼的某處處理對齊問題,我是否總是遇到編譯時錯誤,或者問題可能會保持隱藏狀態,並且在運行時可能會崩潰? – ShitalShah

+0

順便說一句,我已經編輯了我的答案來解決你的最後一個問題。 – ggael

相關問題