2014-06-19 24 views
15

Nel mio progetto ho cambiato il tipo di punto utilizzato da Eigen::Vector2f a Eigen::Vector2d e ho riscontrato problemi di allineamento.Perché gli elenchi di inizializzatori non sono disponibili quando si modifica l'allocatore di std :: vector?

Ecco una versione semplificata del codice:

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

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

sto ottenendo il seguente errore fase di esecuzione:

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. 

Come l'asserzione-messaggio suggerito, ho letto la richiesta alignment of Fixed-size vectorizable Eigen objects . E anche la sottosezione su STL Containers. E sembra che ho due opzioni:

  1. uso del Eigen::aligned_allocator
  2. o utilizzare la macro EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION.

Entrambi i tentativi non vengono compilati (testati con GCC 4.8.3 e Clang 3.5) poiché il compilatore non è in grado di convertire correttamente l'elenco di inizializzazione.

Ecco il codice alterato:

#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 uscita di errore:

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

Quindi mi chiedo:

  • Perché sono liste di inizializzazione non è disponibile quando si cambia l'allocatore del std::vector?

    • È dovuto all'allineamento?
    • Posso allineare in qualche modo l'elenco di inizializzatore?
  • Perché la versione di specializzazione non funziona?

    • Questi mancano della funzionalità di elenco di inizializzazione?

risposta

15

Dopo aver studiato il Eigen/StdVector include file (per la precisione è in Eigen/src/StlSupport/StdVector.h line 68 of version 3.2.1), sembra che il problema ha origine da un modello di specializzazione parziale del std::vector all'interno di questo file di intestazione. Questa specializzazione di modello parziale sostituisce STL vector non appena si utilizza Eigen::aligned_allocator come allocatore. E questa specializzazione sembra mancare delle funzionalità di C++ 11.

In dettaglio perché questa specializzazione è necessario parte sostituendo l'allocatore: Prima C++ 11 la resize function del std::vector potrebbe richiedere un ulteriore parametro al valore per inizializzare elementi appena creati. According to the Eigen3 Documentation passando un parametro per valore scarta qualsiasi modificatore di allineamento e non può essere utilizzato con oggetti Eigen vettorizzabili a dimensione fissa (vedere SIMD).

Edit: Dopo un po 'di più test mi sono reso conto che l'implementazione C++ 11 della std::vector non ha il problema sopraindicato. Pertanto, per risolvere il problema di allineamento, è necessario aggiungere allo Eigen::aligned_allocator. Ma non include Eigen/StdVector. L'inclusione di questo file impedisce di utilizzare l'implementazione C++ 11 di std::vector poiché questa intestazione definisce una specializzazione parziale con Eigen::aligned_allocator come allocatore.