问题
I like to place Eigen fixed-size matrices into the shared memory. But on execution I am getting the following error:
/usr/include/eigen3/Eigen/src/Core/DenseStorage.h:78:
Eigen::internal::plain_array<T, Size, MatrixOrArrayOptions, 16>::plain_array()
[with T = double; int Size = 2; int MatrixOrArrayOptions = 0]:
Assertion `(reinterpret_cast<size_t>(eigen_unaligned_array_assert_workaround_gcc47(array)) & 0xf) == 0 &&
"this assertion is explained here: "
"http://eigen.tuxfamily.org/dox-devel/group__TopicUnalignedArrayAssert.html"
" **** READ THIS WEB PAGE !!! ****"' failed.
Aborted (core dumped)
Using the Eigen define EIGEN_DONT_ALIGN
using cmake with add_definitions(-DEIGEN_DONT_ALIGN)
fixes my problem but I like to know what problem rises and what are the downsides.
There is my example:
#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/container/scoped_allocator.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/containers/vector.hpp>
#include <boost/algorithm/string.hpp>
#include <Eigen/Dense>
using namespace boost::interprocess;
using namespace boost::container;
typedef managed_shared_memory::segment_manager segment_manager_t;
typedef scoped_allocator_adaptor<allocator<void, segment_manager_t> > void_allocator;
typedef void_allocator::rebind<Eigen::Matrix<double,2,1>>::other eigen_allocator;
typedef vector<Eigen::Matrix<double,2,1>, eigen_allocator> eigen_vector;
class CheckPoints {
public:
bool valid;
eigen_vector points;
typedef void_allocator allocator_type;
//Since void_allocator is convertible to any other allocator<T>, we can simplify
//the initialization taking just one allocator for all inner containers.
CheckPoints ( const allocator_type &void_alloc )
: valid ( true ), points ( void_alloc ) {}
CheckPoints ( CheckPoints const& other, const allocator_type &void_alloc )
: valid ( other.valid ), points ( other.points, void_alloc ) {}
friend std::ostream &operator << ( std::ostream &os, const CheckPoints &o ) {
os << o.valid;
for ( size_t i = 0; i < o.points.size(); i++ )
os << ", <" << o.points[i] ( 0,0 ) << ", " << o.points[i] ( 1,0 ) << ">";
return os;
}
};
typedef void_allocator::rebind<CheckPoints>::other checkpoints_allocator;
typedef vector<CheckPoints, checkpoints_allocator> checkpoints_vector;
class Trajectories {
public:
Trajectories ( const void_allocator &void_alloc )
: trajectory ( void_alloc )
{}
Eigen::Matrix<double,2,1> base;
checkpoints_vector trajectory;
friend std::ostream &operator << ( std::ostream &os, const Trajectories &o ) {
os << "base: " << o.base << std::endl;
for ( size_t i = 0; i < o.trajectory.size(); i++ ) os << o.trajectory[i] << std::endl;
return os;
}
};
int main ( int argc, char **argv ) {
using namespace boost::interprocess;
//Remove shared memory on if called with c or clear
if ( argc > 1 && (boost::iequals ( "clear", argv[1] ) || boost::iequals ( "c", argv[1] ) ) ) {
std::cout << "Remove shared memory" << std::endl;
shared_memory_object::remove ( "MySharedMemory" );
}
//Create shared memory
managed_shared_memory segment ( open_or_create,"MySharedMemory", 16*1024*1024 );
//An allocator convertible to any allocator<T, segment_manager_t> type
void_allocator alloc_inst ( segment.get_segment_manager() );
Trajectories *trajectories = segment.find_or_construct<Trajectories> ( "Trajectories" ) ( alloc_inst );
if ( trajectories->trajectory.size() != 10 ) {
std::cout << "Create Data" << std::endl;
trajectories->trajectory.resize ( 10 );
for ( size_t i = 0; i < trajectories->trajectory.size(); i++ ) {
trajectories->trajectory[i].points.resize ( i+1 );
for ( size_t j = 0; j < trajectories->trajectory[i].points.size(); j++ ) {
trajectories->trajectory[i].points[j] ( 0,0 ) = j*2;
trajectories->trajectory[i].points[j] ( 1,0 ) = j*2+1;
}
}
} else {
std::cout << "Data Exists" << std::endl;
}
std::cout << *trajectories << std::endl;
}
回答1:
As explained when following the link provided in the error message, you have to use a memory aligned allocator for eigen_vector
, for instance the one provided by Eigen: Eigen::aligned_allocator
.
Working around this issue by disabling alignment with EIGEN_DONT_ALIGN
also disable Eigen's explicit vectorization. Actually it is enough to disable static alignment only with EIGEN_DONT_ALIGN_STATICALLY
in which case you loose vectorization for small fixed size matrices only. A third and even better option would be to use a non aligned type:
typedef vector<Eigen::Matrix<double,2,1,Eigen::DontAlign>, eigen_allocator> eigen_vector;
in which case you loose vectorization for these objects only.
来源:https://stackoverflow.com/questions/28066275/eigen-fixed-size-matrices-in-shared-memory-using-boost-interprocess