2010-06-23 15 views
9

Używam CentOS 5.4 x86_64 i Zwiększ 1.42.0 na klastrze, który używa Open-MPI 1.3.3. Piszę wspólną bibliotekę, która wykorzystuje pamięć współdzieloną do przechowywania dużych ilości danych do wykorzystania w wielu procesach. Jest też aplikacja ładująca, która odczyta dane z plików i załaduje je do pamięci współdzielonej.Wzmocnienie :: Błąd wspólnej szyny pamięci międzyprocesowej

Po uruchomieniu aplikacji ładującej, określa ilość pamięci potrzebnej do przechowywania danych, a następnie dodaje 25% na obciążenie. Za prawie każdy plik będzie wart ponad 2 gigabajty danych. Kiedy wykonuję żądanie pamięci za pomocą biblioteki Interprocess Boost, oznacza to, że pomyślnie zarezerwowała żądaną ilość pamięci. Ale kiedy używam go, aby zacząć go używać, otrzymuję komunikat "Błąd magistrali". Z tego, co wiem, błąd magistrali wynika z dostępu do pamięci poza zakresem dostępnym dla segmentu pamięci.

Więc zacząłem się zastanawiać, jak pamięć współdzielona jest w systemie Linux i co sprawdzić, aby upewnić się, że mój system jest poprawnie skonfigurowany, aby umożliwić dużą ilość pamięci współdzielonej.

  1. Patrzyłem na "Pliki" w /proc/sys/kernel/shm*:
    • shmall - 4294967296 (4 GB)
    • shmmax - 68719476736 (68 Gb)
    • shmmni - 4096

  2. Wywołałem polecenie 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

Z tego co wiem, ustawienia te wskazują, że powinienem móc przydzielić wystarczającą ilość pamięci współdzielonej do moich celów. Stworzyłem więc uproszczoną programu, który stworzył duże ilości danych w pamięci współdzielonej:


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

skompilowany z linii:

g++ ShmTest.cpp -lboost_system -lrt

pobiegł go z poniższej wyjściu (edytowany, aby go zmniejszyć):

 
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 

po uruchomieniu programu z parametrem (każdy będzie działać, wystarczy zwiększyć argc), to przydzielenia wektora ale nadal będzie skutkować bu s błąd w tym samym indeksie tablicy.

Sprawdziłem wielkości „plików” na /dev/shm używając polecenia ls -ash /dev/shm:

 
total 2.0G 
    0 .  0 .. 2.0G ShmTest 

I tak jak z moim pierwotnym wniosku, że wielkość przydzielonej pamięci współdzielonej jest kaucyjna na 2 koncertach. Biorąc pod uwagę, że "pomyślnie" przydzielono 2352000000 bajtów pamięci, w gigabajtach (używając 1024 * 1024 * 1024) powinno być 2,19 Gb.

Kiedy uruchomić mój rzeczywisty program do ładowania danych przy użyciu MPI, mam to wyjście błędu:

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

ja naprawdę nie wiem, gdzie iść z tym. Czy ktoś ma jakieś sugestie, co wypróbować?


Wysłany do Boost, bug trac na: https://svn.boost.org/trac/boost/ticket/4374

Odpowiedz

8

Cóż, jeśli nadal szuka odpowiedzi na tyle długo ...

W systemie Linux wspólne mechanizmy pamięci zastosowań (tmpfs) przez domyślnie ogranicza go do połowy pamięci RAM systemu. Tak więc w moim klastrze jest to 2 GB, ponieważ mamy 4 GB pamięci systemowej. Więc kiedy próbował przydzielić segment pamięci wspólnej, przydzielono mu maksymalny rozmiar pozostały na /dev/shm.

Ale problem pojawił się, gdy biblioteka Boost nie wskazała błędu lub nawet zgłosiła prawidłową ilość wolnej pamięci, gdy nie mogła przydzielić żądanej ilości pamięci. To było po prostu szczęśliwe, że najwyraźniej podskakiwało, dopóki nie dotarło do końca segmentu, a potem zostało zmaltretowane.

Długookresowym rozwiązaniem jest aktualizacja pliku /etc/fstab, aby wprowadzić zmianę na stałe, ale można uruchomić wywołanie linii poleceń w celu zwiększenia rozmiaru dostępnej pamięci współużytkowanej w każdym węźle do czasu ponownego uruchomienia.

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

Jeżeli XXX to ilość pamięci, aby dostępny (na przykład size=4G).

Zostało to ustalone/wzięte z http://www.cyberciti.biz/tips/what-is-devshm-and-its-practical-usage.html

+1

Interesujące. Powinieneś opublikować coś na liście deweloperów boost. przy okazji, myślę, że możesz zaakceptować własną odpowiedź :) Dzięki za odpowiedź. – neuro

+0

Tak, trochę frustrujące. :) Wysłałem to do śledzenia błędów Boost na https://svn.boost.org/trac/boost/ticket/4374. – CuppM

Powiązane problemy