使用boost进程在共享内存中的特征固定大小矩阵

时间:2015-01-21 11:36:19

标签: c++ alignment shared-memory eigen boost-interprocess

我喜欢将Eigen固定大小的矩阵放入共享内存中。 但在执行时我收到以下错误:

 /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)

使用带有EIGEN_DONT_ALIGN的cmake使用Eigen定义add_definitions(-DEIGEN_DONT_ALIGN)解决了我的问题,但我想知道问题出现了什么以及缺点是什么。

有我的例子:

#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 个答案:

答案 0 :(得分:0)

正如在错误消息中提供的link之后所解释的那样,您必须为eigen_vector使用内存对齐的分配器,例如Eigen提供的分配器:Eigen::aligned_allocator

通过禁用与​​EIGEN_DONT_ALIGN的对齐来解决此问题也会禁用Eigen的显式向量化。实际上,仅使用EIGEN_DONT_ALIGN_STATICALLY禁用静态对齐就足够了,在这种情况下,您只会松散小固定大小矩阵的矢量化。第三种甚至更好的选择是使用非对齐类型:

typedef vector<Eigen::Matrix<double,2,1,Eigen::DontAlign>, eigen_allocator>             eigen_vector;

在这种情况下,您只会松开这些对象的矢量化。