2013-04-22 13 views
6

Ho la seguente situazione: Ho scritto alcuni brevi codici di test MPI per scoprire quale combinazione di operazioni di invio e ricezione funziona meglio nel mio codice.C++: errore di corruzione del puntatore strano

Il codice funziona perfettamente sul mio computer (testato con 8 processi), ma non appena eseguo il cluster su cui sto lavorando, ottengo un enorme errore di output di un puntatore danneggiato o doppiamente liberato, questo è l'output: http://pastebin.com/pXTRSf89

Quello che sto facendo nel mio codice è il seguente: chiamo la mia funzione di comunicazione 100K volte e misurare l'ora. Questa funzione è mostrata sotto. Quello che ho scoperto, è che l'errore si verifica sempre nella stessa iterazione (da qualche parte intorno a 6K). Il processorID segnalato cambia tuttavia. L'iterazione è la stessa anche se uso 64 proc anziché 8. Il problema è: non ho assolutamente idea, cosa potrebbe esserci di sbagliato, specialmente perché non ci sono puntatori liberati o assegnati.

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_ è una variabile globale di tipo MPI_Datatype *, innerGridpoints_ e numOuterGridpoints_ sono globali così (so che questo non è un buon stile di codifica, ma ho preso solo per i tempi). Sono abbastanza sicuro che i miei tipi di dati siano corretti, poiché funzionano in un'altra configurazione delle funzioni di comunicazione (ad esempio Irecv seguita da Send).

Nota finale: ho appena provato a eseguire questo con un solo processo. Poi il seguente errore ha accaduto:

Rank 0 [Lun 22 Apr 02:11:23 2013] [c0-0c1s3n0] Fatal error in PMPI_Isend: Errore MPI interno !, errore di stack: PMPI_Isend (148): MPI_Isend (buf = 0x2aaaab7b531c, count = 1, dtype = USER, dest = 0, tag = 1, MPI_COMM_WORLD, request = 0x7fffffffb4d4) failed (unknown)(): Errore MPI interno! _pmiu_daemon (SIGCHLD): [NID 00070] [c0-0c1s3n0] [Lun 22 Apr 02:11:23 2013] PE RANK segnale 0 uscita abortito

Ancora una volta, questo è successo solo sul cluster, ma ha lavorato su la mia macchina

Sono felice per qualsiasi cosa potrei controllare o dove potrebbe essere l'errore! Grazie

+0

Quale marca di CPU funziona e quale marca di CPU non funziona? – Patashu

+0

Mi chiedo se i tuoi suggerimenti non finiscano mai per indicare blocchi di dati che non dovrebbero. Quando fai cose come '& grid [getIndex (livello, 0, 0, numOuterGridpoints_ [livello] + innerGridpoints_ [livello] [2])]', c'è qualche possibilità che punti ad un blocco che non è tuo? Oppure potrebbe esserci una perdita di memoria nella funzione che stai chiamando ... è la stessa identica versione di compilatore/librerie su entrambe le macchine? – Floris

+0

getIndex e getInnerIndex sono solo funzioni di indice incorporate, poiché la griglia è una matrice 3d, dovrebbero andare bene. Il mio PC è un Intel i5, compilato con gcc 4.6.0 (sistema Mac): il cluster è una macchina Cray con CPU Opteron. Ho provato ma il compilatore PGI standard così come il gcc (versione 4.6.3) – Chris

risposta

2

Devi attendere o eseguire un test o qualcosa di simile su quelle richieste MPI create dallo MPI_Isend(), o perderai le risorse interne e, infine, l'arresto anomalo, che è ciò che sta accadendo.

Jeff Squyres lo mette molto bene nel suo blog post at Cisco.

È sapere che quelle Isends stanno completando, ma la libreria MPI non ha alcun modo di sapere questo e ripulire le risorse assegnate e puntata da quelle MPI_Request s. Quanto e quale tipo di risorse sono necessarie dipende da molte cose, inclusa la connessione di rete sottostante (ad esempio, può richiedere risorse di infiniband scarse), quindi non è necessariamente sorprendente che abbia funzionato sulla propria macchina ma non sul cluster .

È possibile risolvere questo con l'aggiunta di

MPI_Waitall(2, request, status); 

dopo ogni fase di MPI_Isend/MPI_Recv() s.

Questo non è solo necessario per ripulire le risorse, è in realtà necessario per la correttezza di un programma con richieste non bloccanti.

+0

In effetti, ora funziona, grazie. Non sapevo che fosse necessario, ho sempre pensato che potessi evitare le Waits se sapessi che tutto viene ricevuto correttamente – Chris