Pagina 1 di 1
[C++] dump di struttura dati se il programma termina male
Inviato: mercoledì 23 aprile 2014, 13:23
da vaeVictis
Ciao a tutti.
Nella speranza di aver indicato correttamente il problema nel titolo, passo rapidamente a spiegare quello che dovrei risolvere.
Sto facendo alcune simulazioni su un cluster.
Quando si lancia la simulazione, va specificato al cluster il tempo macchina che servirà. Questo tempo macchina può essere stimato a priori, ma capita che invece serva più tempo.
Se l'esecuzione del programma sfora dai tempi "richiesti", il sistema operativo del cluster termina "brute force" la simulazione.
Questo comporta la spiacevole, e non poco frequente situazione, in cui una simulazione venga terminata a poco dalla fine (dove per poco si intende che il programma ha quasi finito di fare quello che deve fare).
Ora... la simulazione riguarda l'elaborazione di una struttura dati (un vector di vector) ed è perfettamente deterministica, nel senso che conoscendo la struttura dati nel momento in cui la simulazione viene "terminata" si può far ripartire da dove è defunta.
Mi sto pertanto chiedendo come istruire il programma per poter fare un dump di questa struttura dati, prima di terminare quando gli arriva il "segnale di morte" da parte del sistema operativo (bsd) che gira sul cluster.
Per dump io intendo che la struttura dati venga scritta "in qualche modo" da "qualche parte" e che possa essere poi letta nuovamente in un secondo momento.
Vorrei pertanto qualche consiglio a riguardo.
In caso, ditemi anche se devo chiedere qualche ulteriore informazione all'amministratore del cluster.
Grazie in anticipo

Re: [C++] dump di struttura dati se il programma termina mal
Inviato: mercoledì 23 aprile 2014, 23:56
da bite
Facendo l'ipotesi che bsd (non lo conosco) segua lo standard posix dei segnali:
- se ti manda SIGTERM (o SIGINT, o SIGABRT) potresti fare un handler che scrive i dati su file prima di terminare:
- se invece ti manda SIGKILL, che non si lascia menare per il naso, l'unica possibilità che vedo è di scrivere periodicamente i dati parziali, in modo che alla terminazione forzata tu perda solo il lavoro fatto dall'ultima volta che li hai scritti.
Re: [C++] dump di struttura dati se il programma termina mal
Inviato: giovedì 24 aprile 2014, 0:48
da vaeVictis
Ciao bite!
È davvero un piacere leggerti!
Ho parlato oggi con l'admin e pare che l'opzione migliore sia proprio la seconda che indichi.
La piattaforma è MPI e sembra che non si possa intercettare nulla, anche se io in realtà pensavo non tanto di intercettare i segnali (mi sono espresso male) ma di usare qualche funzione di quelle che (se non ricordo male) servono per fare pulizia quando un programma è chiuso "male" (sto rimembrando cose lette sul gapil che al momento non ho sotto mano).
Pare invece che la soluzione sia quella di mettere un controllo "temporale" internamente allo script bash che lancia il programma in c++.
Quando lo script si accorge dell'imminente e inevitabile conclusione del tempo a disposizione, lancia lui un segnale appropriato che poi verrà gestito internamente.
Dal momento che sto psicofisicamente provato, per oggi è tutto.
Domani vorrei approfittare della tua disponibilità per chiederti qualche consiglio su come gestire al meglio alcuni "piccoli" dettagli
Grazie per l'interessamento
Re: [C++] dump di struttura dati se il programma termina mal
Inviato: giovedì 24 aprile 2014, 1:03
da bite
Farò un salto da queste parti.

Re: [C++] dump di struttura dati se il programma termina mal
Inviato: giovedì 24 aprile 2014, 8:34
da Ikitt
vedi anche se atexit() puo` fare al caso tuo.
Re: [C++] dump di struttura dati se il programma termina mal
Inviato: giovedì 24 aprile 2014, 9:29
da antex
Non credo (neanche su BSD) che gli handler registrati con atexit vengano eseguiti se il programma termina a causa di un segnale. O no?
Re: [C++] dump di struttura dati se il programma termina mal
Inviato: giovedì 24 aprile 2014, 13:57
da vaeVictis
A dire il vero era proprio quello a cui stavo pensando per i vaghi ricordi di quanto avevo appunto letto sul gapil.
Parlando con l'admin è venuto fuori un secondo approccio (descritto sopra) che sembra più semplice da inserire nel codice già esistente.
Vorrei quindi provare entrambe le strade, anche per scopi prettamente didattici. Sebbene penso che la soluzione sarà quanto discusso con l'admin.
Ho però una domanda che si applica ad entrambi i metodi.
Io ho una "struttura dati" da salvare in qualche modo.
Le due quantità sono un array di array (o un vector di vector a seconda della simulazione che sto facendo girare), che rappresenta "quello che evolve" nel tempo, più un unsigned long int che rappresenta il tempo.
Devo salvarli entrambi per poter poi riavviare il tutto leggendo lo stato a cui si è arrivati con l'evoluzione e il tempo a cui si è arrivati.
Quale è il modo migliore per salvare queste due quantità? Su file? Salvo tutti i valori? Comprimo in qualche modo?
Aspetto dritte!

Re: [C++] dump di struttura dati se il programma termina mal
Inviato: giovedì 24 aprile 2014, 17:22
da bite
Quanto sono grossi?
Dubito comunque che valga la pena comprimere. Più i dati somigliano a numeri casuali, meno si comprimono
Con questo non voglio dire che i risultati della tua simulazione sono casuali, eh

Re: [C++] dump di struttura dati se il programma termina mal
Inviato: sabato 26 aprile 2014, 23:31
da vaeVictis
È una matrice quadrata di numeri in virgila mobile di dimensione "notevole", anche 1000x1000. Sebbene io in realtà ne utilizzi solo uno spicchio, devo salvarla tutta per poi rileggerla, insieme ad un altro singolo valore intero.
La matrice è composta di numeri che, localmente, sono quasi uguali. Su grande scala variano. Ma localmente sono molto vicini l'uno all'altro.
Questa condizione però non è detto che sia sempre verificata. Quindi... è una matrice di float quadrata e di dimensione molto grande
Come mi consigli di salvarla?
Re: [C++] dump di struttura dati se il programma termina mal
Inviato: domenica 27 aprile 2014, 17:46
da bite
Un milione di double fa 8 Mb se salvati in binario, non è poi la fine del mondo. Non starei a cercare arzigogoli tipo salvare la differenza tra numeri contigui mettendola in meno di 8 byte.
Com'è allocata la matrice? Tutta contigua? Contigua per riga? Contigua per colonna? Se fosse garantito che è contigua per riga (ad esempio se è un vector<vector<double> >) potresti salvarla per righe dando a write o fwrite l'indirizzo del primo elemento della riga e specificando la dimensione opportuna.
Re: [C++] dump di struttura dati se il programma termina mal
Inviato: lunedì 28 aprile 2014, 16:32
da vaeVictis
Risposta breve
La "cosa" da salvare è il primo elemento di questo "pair":
Codice: Seleziona tutto
std::pair<std::vector<std::vector<long double> >, std::vector<std::vector<long double> > > mat
Risposta articolata (che non so se può esserti utile)
Allora, la "coppia di matrici" mat, di cui devo salvare la prima, è definita come membro nella classe densMat.
L'header della classe è:
Codice: Seleziona tutto
#ifndef densMat_H
#define densMat_H
#include <utility>
#include <vector>
class densMat {
public:
typedef std::vector<long double> ldVec;
unsigned long halfSide;
double dens_o, meanDens;
unsigned long gridDim;
long double initialGridParts;
std::pair<std::vector<ldVec>, std::vector<ldVec> > mat;
densMat(const unsigned long &, const long double &, const long double &);
void update();
};
#endif
Tenendo quindi in considerazione che ho ridefinito i tipi di dato:
il costruttore é:
Codice: Seleziona tutto
densMat::densMat(const unsigned long &bound,
const long double &trapDens,
const long double &gridDens):
halfSide(bound), dens_o(trapDens), meanDens(gridDens),
gridDim((2 * halfSide + 1)),
initialGridParts(meanDens * ((gridDim)*(gridDim) - 1)),
mat(vector< ldVec >(gridDim + 2, ldVec(gridDim + 2, meanDens)),
vector< ldVec >(gridDim + 2, ldVec(gridDim + 2, meanDens)))
{
mat.first[halfSide+1][halfSide+1] = dens_o;
mat.second[halfSide+1][halfSide+1] = dens_o;
}
e io devo fare il dump del primo elemento di questa coppia di matrici:
Codice: Seleziona tutto
mat(vector< ldVec >(gridDim + 2, ldVec(gridDim + 2, meanDens)),
vector< ldVec >(gridDim + 2, ldVec(gridDim + 2, meanDens)))
{
mat.first[halfSide+1][halfSide+1] = dens_o;
mat.second[halfSide+1][halfSide+1] = dens_o;
}
... in quanto le altre "cose" inizializzate nel costruttore non vengono toccate, quindi io so quanto valevano.
Riavvolgendo il nastro

il dato da salvare è il primo elemento di questo pair:
Codice: Seleziona tutto
std::pair<std::vector<std::vector<long double> >, std::vector<std::vector<long double> > > mat
Aspetto tue nuove
p.s.:
Anche se credo di non avere enormi difficoltà a comprendere di cosa si tratti, faccio presente che non ho mai salvato su file binario e sono totalmente ignorante in merito.
p.p.s.:
Dopo aver capito quale sia il modo migliore per fare questo dump, con il fine di poter poi rileggere la matrice salvata, vorrei anche farti un'ulteriore paio di domandine sempre su questo problema. O meglio, sulla lettura.
Re: [C++] dump di struttura dati se il programma termina mal
Inviato: martedì 29 aprile 2014, 0:16
da bite
Capisco bene, le matrici sono due?
Inoltre mi confermi quel che avevo dato per scontato e cioé che non si tratta di matrici sparse (con la maggioranza degli elementi identicamente nulli)?
I metodi potrebbero essere questi:
Codice: Seleziona tutto
int densMat::dump (const char * pathname)
{
int fd = open (pathname, O_CREAT | O_TRUNC | O_WRONLY | O_SYNC, S_IRWXU);
if (fd < 0) return -1;
ssize_t outcome;
outcome = write (fd, &halfSide, sizeof(halfSide));
if (outcome <= 0) {
close (fd);
unlink (pathname);
return -1;
}
size_t count = sizeof (long double) * (gridDim + 2);
for (unsigned long row = 0; row < gridDim + 2; row++) {
outcome = write (fd, &mat.first[row][0], count);
if (outcome < count) {
close (fd);
unlink (pathname);
return -1;
}
}
for (unsigned long row = 0; row < gridDim + 2; row++) {
outcome = write (fd, &mat.second[row][0], count);
if (outcome < count) {
close (fd);
unlink (pathname);
return -1;
}
}
return 0;
}
int densMat::load (const char * pathname)
{
int fd = open (pathname, O_RDONLY);
if (fd < 0) return -1;
ssize_t outcome;
outcome = read (fd, &halfSide, sizeof(halfSide));
if (outcome <= 0) {
close (fd);
unlink (pathname);
return -1;
}
gridDim = 2 * halfSide + 1;
size_t count = sizeof (long double) * (gridDim + 2);
for (unsigned long row = 0; row < gridDim + 2; row++) {
outcome = read (fd, &mat.first[row][0], count);
if (outcome < count) {
close (fd);
return -1;
}
}
for (unsigned long row = 0; row < gridDim + 2; row++) {
outcome = read (fd, &mat.second[row][0], count);
if (outcome < count) {
close (fd);
return -1;
}
}
close (fd);
return 0;
}
Se ritornano -1 devi controllare errno.
S_IRWXU presume che il file dati non debba essere reso accessibile ad altri.
Ti conviene fare una prova di scrittura e rilettura in locale prima di mandarlo nel cluster.
Curiosità: perché passi parametri long double e poi li metti dentro a double?
Ciao
Re: [C++] dump di struttura dati se il programma termina mal
Inviato: martedì 29 aprile 2014, 0:20
da bite
Ah scusa, vedo adesso che devi salvare solo il primo elemento del pair. Beh, basta togliere il secondo for.
Re: [C++] dump di struttura dati se il programma termina mal
Inviato: martedì 29 aprile 2014, 0:45
da vaeVictis
Ci mancherebbe!
Colpa mia: ho rieditato un paio di volte il messaggio precedente perché mi ero accorto di non essere stato per niente chiaro
Provo, elucubro e mi rifaccio vivo.
Grazie mille per la disponibilità.
p.s.:
Rispondo a tutto domani, massimo dopodomani.
Sto cerebralmente accartocciato.