Ускорить межпроцессную компиляцию unordered_map

Я использую boost 1.53 и GCC 4.1.2. Я пытался использовать boost unordered_map в некоторых тестах (в документации сказано, что он должен работать с разделяемой памятью), но я не могу скомпилировать свой код. С interprocess::map вместо unordered все ок.

Типы:

typedef boost::interprocess::allocator<char, SegmentManager> CharAllocator;
typedef boost::interprocess::basic_string<char, std::char_traits<char>, CharAllocator> ShmString;
typedef ShmString  HashKeyType;
//ComplexType is a wrapper for internal interprocess::map
typedef ComplexType  HashMappedType;
typedef std::pair<const ShmString, ComplexType> HashValueType;

typedef boost::interprocess::allocator<HashValueType,
  boost::interprocess::managed_shared_memory::segment_manager> HashMemAllocator;

typedef boost::unordered_map
  < HashKeyType           , HashMappedType
  , boost::hash<HashKeyType>  ,std::equal_to<HashKeyType>
  , HashMemAllocator>
TestHashMap;

Распределение:

boost::interprocess::managed_shared_memory segment( boost::interprocess::open_or_create, "MySharedMemory", 65536);
thm_ = segment.construct<TestHashMap>("TestHashMap")
      (3, boost::hash<ShmString>(), std::equal_to<ShmString>()
      , segment.get_allocator<HashValueType>());

Применение:

boost::interprocess::managed_shared_memory segment( boost::interprocess::open_only, "MySharedMemory");
ShmString str("123.345", segment.get_allocator<ShmString>());

ComplexType th("MySharedMemory");

HashValueType value(str, th);
thm_->insert(value);

И вот вывод ошибки:

../boost/include/boost/unordered/detail/allocate.hpp: In instantiation of 'boost::unordered::detail::allocator_traits<boost::interprocess::allocator<boost::unordered::detail::ptr_node<std::pair<const boost::container::basic_string<char, std::char_traits<char>, boost::interprocess::allocator<char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long int, long unsigned int, 0u>, 0ul>, boost::interprocess::iset_index> > >, TINHolderShared> >, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long int, long unsigned int, 0u>, 0ul>, boost::interprocess::iset_index> > >::pointer_to_other<const boost::unordered::detail::ptr_node<std::pair<const boost::container::basic_string<char, std::char_traits<char>, boost::interprocess::allocator<char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long int, long unsigned int, 0u>, 0ul>, boost::interprocess::iset_index> > >, TINHolderShared> > >':
../boost/include/boost/unordered/detail/allocate.hpp:527:   instantiated from 'boost::unordered::detail::allocator_traits<boost::interprocess::allocator<boost::unordered::detail::ptr_node<std::pair<const boost::container::basic_string<char, std::char_traits<char>, boost::interprocess::allocator<char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long int, long unsigned int, 0u>, 0ul>, boost::interprocess::iset_index> > >, TINHolderShared> >, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long int, long unsigned int, 0u>, 0ul>, boost::interprocess::iset_index> > >'
../boost/include/boost/unordered/detail/unique.hpp:114:   instantiated from 'boost::unordered::detail::pick_node<boost::interprocess::allocator<std::pair<const boost::container::basic_string<char, std::char_traits<char>, boost::interprocess::allocator<char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long int, long unsigned int, 0u>, 0ul>, boost::interprocess::iset_index> > >, TINHolderShared>, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long int, long unsigned int, 0u>, 0ul>, boost::interprocess::iset_index> >, std::pair<const boost::container::basic_string<char, std::char_traits<char>, boost::interprocess::allocator<char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long int, long unsigned int, 0u>, 0ul>, boost::interprocess::iset_index> > >, TINHolderShared> >'
../boost/include/boost/unordered/detail/unique.hpp:158:   instantiated from 'boost::unordered::detail::map<boost::interprocess::allocator<std::pair<const boost::container::basic_string<char, std::char_traits<char>, boost::interprocess::allocator<char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long int, long unsigned int, 0u>, 0ul>, boost::interprocess::iset_index> > >, TINHolderShared>, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long int, long unsigned int, 0u>, 0ul>, boost::interprocess::iset_index> >, boost::container::basic_string<char, std::char_traits<char>, boost::interprocess::allocator<char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long int, long unsigned int, 0u>, 0ul>, boost::interprocess::iset_index> > >, TINHolderShared, boost::hash<boost::container::basic_string<char, std::char_traits<char>, boost::interprocess::allocator<char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long int, long unsigned int, 0u>, 0ul>, boost::interprocess::iset_index> > > >, std::equal_to<boost::container::basic_string<char, std::char_traits<char>, boost::interprocess::allocator<char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long int, long unsigned int, 0u>, 0ul>, boost::interprocess::iset_index> > > > >'
../boost/include/boost/unordered/unordered_map.hpp:59:   instantiated from 'boost::unordered::unordered_map<boost::container::basic_string<char, std::char_traits<char>, boost::interprocess::allocator<char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long int, long unsigned int, 0u>, 0ul>, boost::interprocess::iset_index> > >, TINHolderShared, boost::hash<boost::container::basic_string<char, std::char_traits<char>, boost::interprocess::allocator<char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long int, long unsigned int, 0u>, 0ul>, boost::interprocess::iset_index> > > >, std::equal_to<boost::container::basic_string<char, std::char_traits<char>, boost::interprocess::allocator<char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long int, long unsigned int, 0u>, 0ul>, boost::interprocess::iset_index> > > >, boost::interprocess::allocator<std::pair<const boost::container::basic_string<char, std::char_traits<char>, boost::interprocess::allocator<char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long int, long unsigned int, 0u>, 0ul>, boost::interprocess::iset_index> > >, TINHolderShared>, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long int, long unsigned int, 0u>, 0ul>, boost::interprocess::iset_index> > >'
utest/THUnitTests.cc:96:   instantiated from here
../boost/include/boost/unordered/detail/allocate.hpp:523: error: ambiguous class template instantiation for 'struct boost::pointer_to_other<boost::interprocess::offset_ptr<boost::unordered::detail::ptr_node<std::pair<const boost::container::basic_string<char, std::char_traits<char>, boost::interprocess::allocator<char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long int, long unsigned int, 0u>, 0ul>, boost::interprocess::iset_index> > >, TINHolderShared> >, long int, long unsigned int, 0u>, const boost::unordered::detail::ptr_node<std::pair<const boost::container::basic_string<char, std::char_traits<char>, boost::interprocess::allocator<char, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long int, long unsigned int, 0u>, 0ul>, boost::interprocess::iset_index> > >, TINHolderShared> > >'
../boost/include/boost/interprocess/offset_ptr.hpp:721: error: candidates are: struct boost::pointer_to_other<boost::interprocess::offset_ptr<T1, P1, O1, A1>, U>
../boost/include/boost/pointer_to_other.hpp:29: error:                 struct boost::pointer_to_other<Sp<T>, U>
../boost/include/boost/pointer_to_other.hpp:36: error:                 struct boost::pointer_to_other<Sp<T, T2>, U>
../boost/include/boost/pointer_to_other.hpp:43: error:                 struct boost::pointer_to_other<Sp<T, T2, T3>, U>

Я не уверен, что проблема в моем коде или из-за старой версии компилятора. Если проблема связана с компилятором, то можно ли ее исправить с помощью более новой версии boost? (я не могу обновить свой GCC). Или, может быть, есть какие-то реализации хеш-таблиц, совместимые с разделяемой памятью и с моим компилятором?


person trvecvlt    schedule 10.04.2015    source источник
comment
@MikeSeymour, только что проверил, моя ошибка, у меня 4.1.2. Если бы я мог выбрать версию GCC, я бы немедленно обновил ее, но я ничего не могу с этим поделать.   -  person trvecvlt    schedule 10.04.2015
comment
boost::interprocess::string не автоматически распределяется (он не использует межпроцессные распределители, если вы не укажете). То же самое для bip::map Опубликовать SSCCE. Ваш образец не является самодостаточным.   -  person sehe    schedule 10.04.2015
comment
@sehe, я добавил определения типов для своей строки. о карте, я не уверен, что должен публиковать здесь ComplexType распределение, потому что оно довольно большое и не совсем связано с проблемой (оно опубликовано в другом вопрос ). Если я изменю unordererd_map на bip::map, этот код скомпилируется с текущим типом ComplexType, поэтому я думаю, что проблема где-то в другом месте.   -  person trvecvlt    schedule 10.04.2015
comment
Я прокомментировал другой вопрос. Посмотрите на мой ответ. Я буду рад узнать, что еще требует разъяснений   -  person sehe    schedule 10.04.2015


Ответы (1)


Вот исправленная версия.

Я просто попытался сделать его самодостаточным в соответствии с наводящими на размышления комментариями. И это работает.

Надеюсь, что это все равно поможет:

Жить на Coliru

#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/containers/string.hpp>
#include <boost/interprocess/containers/map.hpp>
#include <boost/unordered_map.hpp>

namespace bip = boost::interprocess;
// ShmString is boost::interprocess::basic_string
typedef bip::allocator<char, bip::managed_shared_memory::segment_manager> CharAllocator;
typedef bip::basic_string<char, std::char_traits<char>, CharAllocator> ShmString;
typedef ShmString HashKeyType;
// ComplexType is a wrapper for internal interprocess::map
struct ComplexType {
    typedef bip::allocator<std::pair<int const, int>, bip::managed_shared_memory::segment_manager> Alloc;
    typedef bip::map<int, int, std::less<int>, Alloc> Map;

    template <typename Alloc2>
    ComplexType(std::string, Alloc2 const& alloc = {}) : map(alloc) {}
    Map map;
};

typedef ComplexType HashMappedType;
typedef std::pair<const ShmString, ComplexType> HashValueType;
typedef bip::allocator<HashValueType, bip::managed_shared_memory::segment_manager> HashMemAllocator;
typedef boost::unordered_map<HashKeyType, HashMappedType, boost::hash<HashKeyType>, std::equal_to<HashKeyType>, HashMemAllocator>
    TestHashMap;

int main()
{
    // Allocation:
    {
        bip::managed_shared_memory segment(bip::open_or_create, "MySharedMemory", 65536);
        auto thm_ = segment.construct<TestHashMap>("TestHashMap")(3, boost::hash<ShmString>(), std::equal_to<ShmString>(),
                segment.get_allocator<HashValueType>());

    }
    // Usage:
    bip::managed_shared_memory segment(bip::open_only, "MySharedMemory");
    auto thm_ = segment.construct<TestHashMap>("TestHashMap")(3, boost::hash<ShmString>(), std::equal_to<ShmString>(), segment.get_allocator<HashValueType>());
    ShmString str("123.345", segment.get_allocator<ShmString>());

    ComplexType th("MySharedMemory", segment.get_segment_manager());

    HashValueType value(str, th);
    thm_->insert(value);
}
person sehe    schedule 10.04.2015
comment
Какую версию GCC вы используете? Есть auto, так что думаю, что он вполне современный =) Код выглядит правильно, но на моем GCC 4.1.2 я получаю те же ошибки. Похоже, единственный вариант для меня — попробовать новый буст или просто использовать карты. - person trvecvlt; 10.04.2015
comment
Я предполагаю, что вы заменили auto на имя типа? Вы уверены, что у вас нет какой-то вещи, использующей пространство имен, которая сеет хаос? (Даже если они встроены в какое-то пространство имен в заголовке). К вашему сведению Распределители имеют конструкторы преобразования (неявные повторные привязки), и вы также можете неявно создавать их из mmf.get_segment_manager(). Также см. комментарий к предыдущему вопросу. - person sehe; 10.04.2015
comment
Хотя подождите секунду. auto поддержка была выпущена в GCC 4.4 с 21 апреля 2009 г.. Я не понимаю, как 6 лет можно приравнять к вполне современному =) - person sehe; 10.04.2015
comment
да, я заменил его. Я удалил все включения, кроме system и boost, и прокомментировал весь свой код, поэтому единственная разница заключается в типе вместо auto и отсутствии инициализатора по умолчанию здесь Alloc2 const& alloc = {}. И спасибо за ссылку под другим вопросом =) - person trvecvlt; 10.04.2015