2013-04-22 15 views
6

Mam następującą sytuację: Napisałem kilka krótkich kodów testowych MPI, aby sprawdzić, która kombinacja operacji wysyłania i odbierania działa najlepiej w moim kodzie.C++: Błąd uszkodzenia dziwnego wskaźnika

Kod działa doskonale na moim własnym komputerze (testowany z 8 procesami), ale gdy tylko uruchomię go w klastrze, nad którym pracuję, otrzymuję duży błąd w postaci uszkodzonego lub podwójnie zwalnianego wskaźnika, to jest wyjście: http://pastebin.com/pXTRSf89

Co robię w moim kodzie jest następujący: Wzywam moją funkcję komunikacyjną 100K razy i mierzę czas. Ta funkcja jest pokazana poniżej. Odkryłem, że błąd zawsze występuje w tej samej iteracji (gdzieś około 6K). Podany ID procesora zmienia się jednak. Iteracja jest taka sama, nawet jeśli używam 64 proc zamiast 8. Problem polega na tym, że nie mam absolutnie żadnego pojęcia, co może być nie tak, zwłaszcza, że ​​nie ma wskaźnika zwolnionego lub przypisanego.

void communicateGrid(int level, real* grid, const Subdomain& subdomain, std::vector<TimeMap>& tm_) { 
    tm_[level]["CommGrid"].start(); 

    MPI_Status status[2]; 
    MPI_Request request[2]; 

    // x 
    MPI_Isend(&grid[getIndexInner(level, 1, 1, 1) + innerGridpoints_[level][0] - numOuterGridpoints_[level]], 1, mpiTypes_[level * 4 + 1], subdomain.upperNeighbors[0], 0, MPI_COMM_WORLD, &request[0]); 
    MPI_Isend(&grid[getIndexInner(level, 1, 1, 1)], 1, mpiTypes_[level * 4 + 1], subdomain.lowerNeighbors[0], 1, MPI_COMM_WORLD, &request[1]); 

    MPI_Recv(&grid[getIndexInner(level, 1,1,1) + innerGridpoints_[level][0]], 1, mpiTypes_[level * 4 + 1], subdomain.upperNeighbors[0], 1, MPI_COMM_WORLD, &status[0]); 
    MPI_Recv(&grid[getIndexInner(level, 1,1,1) - numOuterGridpoints_[level]], 1, mpiTypes_[level * 4 + 1], subdomain.lowerNeighbors[0], 0, MPI_COMM_WORLD, &status[1]); 

    //y 
    MPI_Isend(&grid[getIndex(level, 0, innerGridpoints_[level][1], 0)], 1, mpiTypes_[level * 4 + 2], subdomain.upperNeighbors[1], 2, MPI_COMM_WORLD, &request[0]); 
    MPI_Isend(&grid[getIndex(level, 0, numOuterGridpoints_[level], 0)], 1, mpiTypes_[level * 4 + 2], subdomain.lowerNeighbors[1], 3, MPI_COMM_WORLD, &request[1]); 

    MPI_Recv(&grid[getIndex(level, 0, innerGridpoints_[level][1] + numOuterGridpoints_[level], 0)], 1, mpiTypes_[level * 4 + 2], subdomain.upperNeighbors[1], 3, MPI_COMM_WORLD, &status[0]); 
    MPI_Recv(grid, 1, mpiTypes_[level * 4 + 2], subdomain.lowerNeighbors[1], 2, MPI_COMM_WORLD, &status[1]); 

    // z 
    MPI_Isend(&grid[getIndex(level, 0, 0, innerGridpoints_[level][2])], 1, mpiTypes_[level * 4 + 3], subdomain.upperNeighbors[2], 4, MPI_COMM_WORLD, &request[0]); 
    MPI_Isend(&grid[getIndex(level, 0, 0, numOuterGridpoints_[level])], 1, mpiTypes_[level * 4 + 3], subdomain.lowerNeighbors[2], 5, MPI_COMM_WORLD, &request[1]); 

    MPI_Recv(&grid[getIndex(level, 0, 0, numOuterGridpoints_[level] + innerGridpoints_[level][2])], 1, mpiTypes_[level * 4 + 3], subdomain.upperNeighbors[2], 5, MPI_COMM_WORLD, &status[0]); 
    MPI_Recv(grid, 1, mpiTypes_[level * 4 + 3], subdomain.lowerNeighbors[2], 4, MPI_COMM_WORLD, &status[1]); 

    tm_[level]["CommGrid"].stop(); 
} 

mpiTypes_ jest globalną zmienną typu MPI_Datatype *, innerGridpoints_ i numOuterGridpoints_ są globalne, jak również (wiem, że to nie jest dobry styl kodowania, ale wziąłem go tylko do czasu). Jestem prawie pewien, że moje typy danych są poprawne, ponieważ działają w innym zestawie funkcji komunikacyjnych (np. Irecv, a następnie Send).

Ostatnia uwaga: Po prostu próbowałem uruchomić to za pomocą tylko jednego procesu. Następnie wystąpił następujący błąd:

Rank 0 [Mon 22 kwietnia 02:11:23 2013] [c0-0c1s3n0] Błąd krytyczny w PMPI_Isend: Błąd wewnętrzny MPI !, błąd stosu: PMPI_Isend (148): MPI_Isend (buf = 0x2aaaab7b531c, count = 1, dtype = USER, dest = 0, tag = 1, MPI_COMM_WORLD, request = 0x7fffffffb4d4) failed (unknown)(): Wewnętrzny błąd MPI! _pmiu_daemon (SIHCHLD) [NID 00070] [c0-0c1s3n0] [02:11:23 Pon 22 kwietnia 2013] PE RANK sygnał 0 wyjście przerwane

Ponownie, stało się to tylko w zestawie, ale pracował moja maszyna.

Jestem szczęśliwy za wszystko, co mógłbym sprawdzić lub gdzie może być błąd! Dzięki

+0

Jaką markę procesora obsługuje i jakiej marki procesor zawodzi? – Patashu

+0

Zastanawiam się, czy Twoje wskazówki nigdy nie wskażą bloków danych, których nie powinny. Kiedy robisz rzeczy takie jak '& grid [getIndex (level, 0, 0, numOuterGridpoints_ [level] + innerGridpoints_ [level] [2])], czy jest jakaś szansa, że ​​to wskazuje na blok, który nie jest twój? Czy może nastąpić przeciek pamięci w funkcji, którą wywołujesz ... Czy jest to dokładnie ta sama wersja kompilatora/bibliotek na obu komputerach? – Floris

+0

getIndex i getInnerIndex są po prostu inkrementowanymi funkcjami indeksowymi, ponieważ siatka jest tablicą 3D, powinny być w porządku. Mój komputer to Intel i5, skompilowany z gcc 4.6.0 (system Mac) - klaster to maszyna Cray z procesorami Opteron. Próbowałem, ale standardowy kompilator PGI, jak również gcc (wersja 4.6.3) – Chris

Odpowiedz

2

Musisz poczekać, przetestować lub coś w tych żądaniach MPI utworzonych przez MPI_Isend(), bo inaczej wyciekniesz zasoby wewnętrzne i ostatecznie się zawiesisz, co się dzieje.

Jeff Squyres przedstawia to bardzo dobrze w swoim blog post at Cisco.

Wiesz, że te Isends kończą, ale biblioteki MPI nie ma możliwości dowiedzenia się tego i oczyszczania zasoby przydzielone i wskazywanego przez tych MPI_Request s. To, ile i jakie zasoby są wymagane, zależy od wielu rzeczy, w tym od podstawowego połączenia sieciowego (może na przykład obejmować niewielkie zasoby infiniband), więc niekoniecznie jest zaskakujące, że działało na komputerze użytkownika, ale nie w klastrze. .

Można rozwiązać ten problem poprzez dodanie

MPI_Waitall(2, request, status); 

po każdym etapie MPI_Isend/MPI_Recv() s.

Nie jest to konieczne tylko do czyszczenia zasobów, tak naprawdę jest wymagane dla poprawności programu z niezablokowanymi żądaniami.

+0

Rzeczywiście, teraz to działa, dziękuję. Nigdy nie wiedziałem, że to konieczne, zawsze myślałem, że możesz uniknąć Waitów, jeśli wiesz, że wszystko zostanie poprawnie odebrane – Chris

Powiązane problemy