15

私のプロジェクトでは、使用するポイント タイプを から に変更したところEigen::Vector2fEigen::Vector2d位置合わせの問題が発生しました。

コードの簡略版は次のとおりです。

#include <vector>
#include <Eigen/Eigen>

int main()
{
    std::vector<Eigen::Vector2d> points = { {0,0}, {0,1} };
}

次の実行時エラーが発生します。

eigen3/Eigen/src/Core/DenseStorage.h:78: Eigen::internal::plain_array<double, 2, 0, 16>::plain_array() [T = double, Size = 2, MatrixOrArrayOptions = 0, Alignment = 16]: Assertion `(reinterpret_cast<size_t>(array) & 0xf) == 0 && "this assertion is explained here: " "http://eigen.tuxfamily.org/dox-devel/group__TopicUnalignedArrayAssert.html" " **** READ THIS WEB PAGE !!! ****"' failed.

assert-message が示唆しているように、Fixed-size vectorizable Eigen objects の必要な配置について読みました。また、STL Containersに関するサブセクション。そして、私には2つのオプションがあるようです:

  1. 使用Eigen::aligned_allocator
  2. またはEIGEN_DEFINE_STL_VECTOR_SPECIALIZATIONマクロを使用します。

コンパイラは初期化子リストを適切に変換できないため、どちらの試行もコンパイルされません (GCC 4.8.3 および Clang 3.5 でテスト済み)。

変更されたコードは次のとおりです。

#include <vector>
#include <Eigen/Eigen>
#include <Eigen/StdVector>
// EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION(Eigen::Vector2d)

int main()
{
    std::vector<Eigen::Vector2d, Eigen::aligned_allocator<Eigen::Vector2d>> points = { {0,0}, {0,1} };
    // std::vector<Eigen::Vector2d> points = { {0,0}, {0,1} };
}

GCC エラー出力:

error: could not convert ‘{{0, 0}, {0, 1}}’ from ‘&lt;brace-enclosed initializer list>’ to ‘std::vector<Eigen::Matrix<double, 2, 1>, Eigen::aligned_allocator<Eigen::Matrix<double, 2, 1> > >’

だから私は疑問に思っています:

  • のアロケータを変更するときにイニシャライザ リストを使用できないのはなぜstd::vectorですか?

    • これはアライメントのせいですか?
    • どうにかして初期化子リストを揃えることはできますか?
  • 特殊化バージョンが失敗するのはなぜですか?

    • これらには初期化子リスト機能がありませんか?
4

1 に答える 1

16

Eigen/StdVectorインクルード ファイル (正確にはEigen/src/StlSupport/StdVector.hバージョン 3.2.1 の 68 行目) を調べたところ、問題はstd::vectorこのヘッダー ファイル内の部分的なテンプレートの特殊化に起因するようです。この部分的なテンプレートの特殊化は、アロケータvectorとして使用するとすぐにSTL を置き換えます。Eigen::aligned_allocatorそして、この特殊化には C++11 の機能が欠けているようです。

アロケータの置き換えとは別に、この特殊化が必要な理由の詳細: C++11 より前では、のサイズ変更関数は、std::vector新しく作成された要素を初期化するために、追加のパラメータを値で受け取ることができました。Eigen3 ドキュメンテーションによると、パラメータを値で渡すとアライメント修飾子が破棄され、固定サイズのベクトル化可能な Eigen オブジェクトでは使用できません (SIMD を参照)。

編集: さらにテストを行った結果、C++11 の実装にはstd::vector上記の問題がないことがわかりました。したがって、位置合わせの問題を解決するは、Eigen::aligned_allocator. ただし、含めないでくださいEigen/StdVector。このファイルをインクルードすると、C++11 実装を使用できなくなります。これは、このヘッダーがアロケーターとしてstd::vector部分的な特殊化を定義しているためです。Eigen::aligned_allocator

于 2014-06-21T21:35:06.607 に答える