Boost :: Interprocess Shared Memory Error Error - PullRequest
10 голосов
/ 23 июня 2010

Я использую CentOS 5.4 x86_64 и Boost 1.42.0 в кластере, использующем Open-MPI 1.3.3.Я пишу разделяемую библиотеку, которая использует разделяемую память для хранения больших объемов данных для использования несколькими процессами.Также имеется приложение-загрузчик, которое считывает данные из файлов и загружает их в общую память.

Когда я запускаю приложение загрузчика, оно определяет объем памяти, необходимый для точного хранения данных, а затем добавляет 25% накладных расходов.Почти для каждого файла это будет более 2 гигабайт данных.Когда я делаю запрос памяти, используя библиотеку Boost Interprocess, он говорит, что успешно зарезервировал запрошенный объем памяти.Но когда я начинаю использовать его, я получаю «Ошибка шины».Из того, что я могу сказать, ошибка шины является результатом доступа к памяти за пределами диапазона, доступного для сегмента памяти.

Итак, я начал изучать, как работает общая память в Linux и что нужно проверитьуверен, что моя система правильно настроена на такой большой объем разделяемой памяти.

  1. Я посмотрел на "файлы" на /proc/sys/kernel/shm*:
    • shmall - 4294967296 (4 Гб)
    • shmmax - 68719476736 (68 Гб)
    • shmmni - 4096

  2. Я вызвал команду ipcs -lm:
    ------ Shared Memory Limits --------
    max number of segments = 4096
    max seg size (kbytes) = 67108864
    max total shared memory (kbytes) = 17179869184
    min seg size (bytes) = 1

Из того, что я могу сказать, эти настройки указывают, что я должен быть в состоянии выделить достаточно разделяемой памяти для моих целей.Поэтому я создал урезанную программу, которая создала большие объемы данных в общей памяти:


#include <iostream>

#include <boost/interprocess/managed_shared_memory.hpp>
#include <boost/interprocess/allocators/allocator.hpp>
#include <boost/interprocess/containers/vector.hpp>

namespace bip = boost::interprocess;

typedef bip::managed_shared_memory::segment_manager segment_manager_t;
typedef bip::allocator<long, segment_manager_t> long_allocator;
typedef bip::vector<long, long_allocator> long_vector;

int main(int argc, char ** argv) {
    struct shm_remove  { 
        shm_remove()    { bip::shared_memory_object::remove("ShmTest"); } 
        ~shm_remove()   { bip::shared_memory_object::remove("ShmTest"); } 
    } remover; 

    size_t szLength = 280000000;
    size_t szRequired = szLength * sizeof(long);
    size_t szRequested = (size_t) (szRequired * 1.05);
    bip::managed_shared_memory segment(bip::create_only, "ShmTest", szRequested); 

    std::cout << 
        "Length:       " << szLength << "\n" <<
        "sizeof(long): " << sizeof(long) << "\n" <<
        "Required:     " << szRequired << "\n" <<
        "Requested:    " << szRequested << "\n" <<
        "Allocated:    " << segment.get_size() << "\n" <<
        "Overhead:     " << segment.get_size() - segment.get_free_memory() << "\n" <<
        "Free:         " << segment.get_free_memory() << "\n\n";

    long_allocator alloc(segment.get_segment_manager()); 
    long_vector vector(alloc);

    if (argc > 1) {
        std::cout << "Reserving Length of " << szLength << "\n";
        vector.reserve(szLength);
        std::cout << "Vector Capacity: " << vector.capacity() << "\tFree: " << segment.get_free_memory() << "\n\n";
    }

    for (size_t i = 0; i < szLength; i++) {
        if ((i % (szLength / 100)) == 0) {
            std::cout << i << ": " << "\tVector Capacity: " << vector.capacity() << "\tFree: " << segment.get_free_memory() << "\n";
        }
        vector.push_back(i);    
    }
    std::cout << "end: " << "\tVector Capacity: " << vector.capacity() << "\tFree: " << segment.get_free_memory() << "\n";

    return 0;
}

Скомпилировал ее с помощью строки:

g++ ShmTest.cpp -lboost_system -lrt

Затем запустил ее со следующим выводом (отредактированочтобы сделать его меньше):

Length:       280000000
sizeof(long): 8
Required:     2240000000
Requested:    2352000000
Allocated:    2352000000
Overhead:     224
Free:         2351999776

0:      Vector Capacity: 0      Free: 2351999776
2800000:        Vector Capacity: 3343205        Free: 2325254128
5600000:        Vector Capacity: 8558607        Free: 2283530912
8400000:        Vector Capacity: 8558607        Free: 2283530912
11200000:       Vector Capacity: 13693771       Free: 2242449600
14000000:       Vector Capacity: 21910035       Free: 2176719488
...
19600000:       Vector Capacity: 21910035       Free: 2176719488
22400000:       Vector Capacity: 35056057       Free: 2071551312
...
33600000:       Vector Capacity: 35056057       Free: 2071551312
36400000:       Vector Capacity: 56089691       Free: 1903282240
...
56000000:       Vector Capacity: 56089691       Free: 1903282240
58800000:       Vector Capacity: 89743507       Free: 1634051712
...
89600000:       Vector Capacity: 89743507       Free: 1634051712
92400000:       Vector Capacity: 143589611      Free: 1203282880
...
142800000:      Vector Capacity: 143589611      Free: 1203282880
145600000:      Vector Capacity: 215384417      Free: 628924432
...
212800000:      Vector Capacity: 215384417      Free: 628924432
215600000:      Vector Capacity: 293999969      Free: 16
...
260400000:      Vector Capacity: 293999969      Free: 16
Bus error

Если вы запустите программу с параметром a (любой будет работать, просто нужно увеличить argc), он предварительно выделит вектор, но все равно приведет к шинеошибка в том же индексе массива.

Я проверил размер «файлов» на /dev/shm с помощью команды ls -ash /dev/shm:

total 2.0G
   0 .     0 ..  2.0G ShmTest

И, как и в моем исходном приложении, это размер выделенной общей памятиограничен в 2 концерта.Учитывая, что он «успешно» выделил 2352000000 байт памяти, в гигабайтах (с использованием 1024 *1024* 1024) он должен составлять 2,19 Гб.вывод:

Requested: 2808771120
Recieved: 2808771120

[c1-master:13894] *** Process received signal ***
[c1-master:13894] Signal: Bus error (7)
[c1-master:13894] Signal code:  (2)
[c1-master:13894] Failing at address: 0x2b3190157000
[c1-master:13894] [ 0] /lib64/libpthread.so.0 [0x3a64e0e7c0]
[c1-master:13894] [ 1] ../LookupPopulationLib/Release/libLookupPopulation.so(_ZN5boost12interprocess26uninitialized_copy_or_moveINS0_10offset_ptrIlEEPlEET0_T_S6_S5_PNS_10disable_ifINS0_11move_detail16is_move_iteratorIS6_EEvE4typeE+0x218) [0x2b310dcf3fb8]
[c1-master:13894] [ 2] ../LookupPopulationLib/Release/libLookupPopulation.so(_ZN5boost9container6vectorIlNS_12interprocess9allocatorIlNS2_15segment_managerIcNS2_15rbtree_best_fitINS2_12mutex_familyENS2_10offset_ptrIvEELm0EEENS2_10iset_indexEEEEEE15priv_assign_auxINS7_IlEEEEvT_SG_St20forward_iterator_tag+0xa75) [0x2b310dd0a335]
[c1-master:13894] [ 3] ../LookupPopulationLib/Release/libLookupPopulation.so(_ZN5boost9container17containers_detail25advanced_insert_aux_proxyINS0_6vectorIlNS_12interprocess9allocatorIlNS4_15segment_managerIcNS4_15rbtree_best_fitINS4_12mutex_familyENS4_10offset_ptrIvEELm0EEENS4_10iset_indexEEEEEEENS0_17constant_iteratorISF_lEEPSF_E25uninitialized_copy_all_toESI_+0x1d7) [0x2b310dd0b817]
[c1-master:13894] [ 4] ../LookupPopulationLib/Release/libLookupPopulation.so(_ZN5boost9container6vectorINS1_IlNS_12interprocess9allocatorIlNS2_15segment_managerIcNS2_15rbtree_best_fitINS2_12mutex_familyENS2_10offset_ptrIvEELm0EEENS2_10iset_indexEEEEEEENS3_ISD_SB_EEE17priv_range_insertENS7_ISD_EEmRNS0_17containers_detail23advanced_insert_aux_intISD_PSD_EE+0x771) [0x2b310dd0d521]
[c1-master:13894] [ 5] ../LookupPopulationLib/Release/libLookupPopulation.so(_ZN5boost12interprocess6detail8Ctor3ArgINS_9container6vectorINS4_IlNS0_9allocatorIlNS0_15segment_managerIcNS0_15rbtree_best_fitINS0_12mutex_familyENS0_10offset_ptrIvEELm0EEENS0_10iset_indexEEEEEEENS5_ISF_SD_EEEELb0EiSF_NS5_IvSD_EEE11construct_nEPvmRm+0x157) [0x2b310dd0d9a7]
[c1-master:13894] [ 6] ../LookupPopulationLib/Release/libLookupPopulation.so(_ZN5boost12interprocess15segment_managerIcNS0_15rbtree_best_fitINS0_12mutex_familyENS0_10offset_ptrIvEELm0EEENS0_10iset_indexEE28priv_generic_named_constructIcEEPvmPKT_mbbRNS0_6detail18in_place_interfaceERNS7_INSE_12index_configISB_S6_EEEENSE_5bool_ILb1EEE+0x6fd) [0x2b310dd0c85d]
[c1-master:13894] [ 7] ../LookupPopulationLib/Release/libLookupPopulation.so(_ZN5boost12interprocess15segment_managerIcNS0_15rbtree_best_fitINS0_12mutex_familyENS0_10offset_ptrIvEELm0EEENS0_10iset_indexEE22priv_generic_constructEPKcmbbRNS0_6detail18in_place_interfaceE+0xf8) [0x2b310dd0dd58]
[c1-master:13894] [ 8] ../LookupPopulationLib/Release/libLookupPopulation.so(_ZN7POP_LTL16ExportPopulation22InitializeSharedMemoryEPKc+0x1609) [0x2b310dceea99]
[c1-master:13894] [ 9] ../LookupPopulationLib/Release/libLookupPopulation.so(_ZN7POP_LTL10InitializeEPKc+0x349) [0x2b310dd0ebb9]
[c1-master:13894] [10] MPI_Release/LookupPopulation.MpiLoader(main+0x372) [0x4205d2]
[c1-master:13894] [11] /lib64/libc.so.6(__libc_start_main+0xf4) [0x3a6461d994]
[c1-master:13894] [12] MPI_Release/LookupPopulation.MpiLoader(__gxx_personality_v0+0x239) [0x420009]
[c1-master:13894] *** End of error message ***
--------------------------------------------------------------------------
mpirun noticed that process rank 0 with PID 13894 on node c1-master exited on signal 7 (Bus error).
--------------------------------------------------------------------------

Я действительно не уверен, куда идти с этим.У кого-нибудь есть предложения, что попробовать?

Опубликовано в журнал ошибок Boost по адресу: https://svn.boost.org/trac/boost/ticket/4374

1 Ответ

9 голосов
/ 24 июня 2010

Ну, если вы продолжите искать ответ достаточно долго ...

В Linux механизмы разделяемой памяти, которые он использует (tmpfs) по умолчанию, ограничивают его до половины системной памяти. На моем кластере это 2 Гб, потому что у нас 4 Гб оперативной памяти. Поэтому, когда он пытался выделить сегмент совместно используемой памяти, он выделялся до максимального размера, оставшегося на /dev/shm.

Но проблема возникла, когда библиотека Boost не указала ошибку или даже сообщила правильный объем свободной памяти, когда она не смогла выделить запрошенный объем памяти. Он был просто рад, что, по-видимому, пыхтел, пока не достиг конца сегмента, а затем допустил ошибку.

Долгосрочным решением является обновление файла /etc/fstab для внесения изменений на постоянной основе, но можно выполнить вызов командной строки для увеличения размера доступной общей памяти на каждом узле до перезагрузки.

mount -o remount,size=XXX /dev/shm

Где XXX - это объем доступной памяти (например, size=4G).

Это было выяснено / взято из http://www.cyberciti.biz/tips/what-is-devshm-and-its-practical-usage.html

...