使用Boost Interprocess在共享内存中的本征固定大小矩阵 [英] Eigen fixed-size matrices in shared memory using boost interprocess

查看:130
本文介绍了使用Boost Interprocess在共享内存中的本征固定大小矩阵的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我喜欢将本征固定大小的矩阵放入共享内存中。
但是在执行时出现以下错误:

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)

使用本征定义 EIGEN_DONT_ALIGN 将cmake与 add_definitions(-DEIGEN_DONT_ALIGN)一起使用可解决我的问题,但我想知道出现了什么问题以及不利之处。

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.

有我的例子:

#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;
}


推荐答案

按照<错误消息中提供的href = http://eigen.tuxfamily.org/dox/group__TopicStlContainers.html rel = nofollow>链接,您必须对<$ c $使用内存对齐的分配器c> eigen_vector ,例如Eigen提供的代码: Eigen :: aligned_allocator

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.

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

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.

这篇关于使用Boost Interprocess在共享内存中的本征固定大小矩阵的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆