View Full Version : [C++] Strano problema di ottimizzazione
Ciao ragazzi, ho un problema apparentemente strano. Dunque, io ho una classe StandardBackprop, una ParNeuralNet ed un'altra Test.
La classe TrainingNet ha nel suo header un puntatore alla classe ParNeuralNet. Nella classe ParNeuralNet ho una funzione che è la causa del problema:
inline double ParNeuralNet::randomValue(double symmetric_range){
double zero_one_value=((double)rand()/((double)(RAND_MAX)+1.0));
double result=zero_one_value*(2.0*symmetric_range)-(symmetric_range);
return result;
}
Ora, io richiamo tale funzione dalla classe Test con questa sintassi :
TrainingNet->Par->randomValue(range_max)
TrainingNet è un oggetto StandardBackprop, Par, oggetto ParNeuralNet. La classe StandardBackprop è figlio della classe BackProp, ParNeuralNet invece è una classe singola.
Il problema è che se compilo senza ottimizzazioni, tutto funziona liscio. Se invece metto l'ottimizzazione -O1, -O2, -O3, mi dice "undefined reference " a tale funzione.
Se però la stessa funzione, invece di dichiararla inline, la definisco direttamente nell'header di ParNeuralNet, compila anche con ottimizzazioni !
In pratica, sembra che,a causa della doppia referenziazione per accedere alla funzione, non riesca a fare l'inline direttamente. Avete qualche spiegazione di ciò? Grazie.
Le funzioni inline le devi definire nell'header, devono essere disponibili subito al compilatore per essere espanse (o no, lo decide il compilatore)
Se però la stessa funzione, invece di dichiararla inline, la definisco direttamente nell'header di ParNeuralNet, compila anche con ottimizzazioni !
Se la definisci nella definizione della classe, viene comunque considerata inline anche se non lo spefichi
Le funzioni inline le devi definire nell'header, devono essere disponibili subito al compilatore per essere espanse (o no, lo decide il compilatore)
Se la definisci nella definizione della classe, viene comunque considerata inline anche se non lo spefichi
Ok, ma ho altre funzioni inline nel codice, e non mi compare lo stesso errore. Solo sulla funzione sopra menzionata. Perchè questo ?
EDIT: modifico e mi crea un'altro post..
Ma tutte queste funzioni inline le chiami nello stesso modo (cioè dal puntatore di una classe che chiama una funziona di un'altra classe dal suo puntatore :wtf: :oink: )?
Ma tutte queste funzioni inline le chiami nello stesso modo (cioè dal puntatore di una classe che chiama una funziona di un'altra classe dal suo puntatore :wtf: :oink: )?
No, solo quella. E' lì il problema ?
Ok, ma ho altre funzioni inline nel codice, e non mi compare lo stesso errore. Solo sulla funzione sopra menzionata. Perchè questo ?
Devi dichiarare la funzione inline nell'header file. Compila senza ottimizzazioni perche' il compilatore ignora l'inline, mentre con ottimizzazioni cerca la definizione della funzione e non la trova. Che compilatore stai usando?
Ma soprattutto: perche' hai dichiarato quella funzione inline?
Che compilatore stai usando?
mpicxx, è un wrapper MPI per g++
Ma soprattutto: perche' hai dichiarato quella funzione inline?
Perchè è chiamata moltissime volte ed è corta, quindi è bene dichiararla inline :)
mpicxx, è un wrapper MPI per g++
Ok, perche' il comportamento del compilatore mi pare un po' strano.
Perchè è chiamata moltissime volte ed è corta, quindi è bene dichiararla inline :)
Hai un qualche profiling che dimostri che dichiarare quella funzione inline e' un'ottimizzazione misurabile oppure e' solo una tua ipotesi? :)
ilsensine
20-12-2007, 14:12
Ok, perche' il comportamento del compilatore mi pare un po' strano.
Unrue non è stato chiaro su dove ha messo l'implementazione, se è in un file sorgente allora il comportamento è corretto...
Unrue non è stato chiaro su dove ha messo l'implementazione, se è in un file sorgente allora il comportamento è corretto...
Si', per questo non mi era chiaro dove voleva mettere il corpo della funzione.
Edit:
Contr'ordine, il comportamento del compilatore non e' conforme allo standard.
In questa situazione:
.hpp
class A
{
public:
inline void m();
};
.cpp
inline void A::m()
{
}
Il compilatore deve dare un "undefined reference" sia con ottimizzazioni attivate sia con ottimizzazioni disattivate se m e' referenziato in un'unita' di compilazione diversa da dove e' definito. Non deve semplicemente assumere il non inline quando le ottimizzazioni sono disattivate.
Se una funzione e' dichiarata inline in un'unita' di compilazione, il corpo deve essere definito in quell'unita'. Il comportamento del compilatore in relazione alla semantica del codice non deve cambiare a seconda delle ottimizzazioni.
Si', per questo non mi era chiaro dove voleva mettere il corpo della funzione.
Edit:
Contr'ordine, il comportamento del compilatore non e' conforme allo standard.
In questa situazione:
.hpp
class A
{
public:
inline void m();
};
.cpp
inline void A::m()
{
}
Il compilatore deve dare un "undefined reference" sia con ottimizzazioni attivate sia con ottimizzazioni disattivate se m e' referenziato in un'unita' di compilazione diversa da dove e' definito. Non deve semplicemente assumere il non inline quando le ottimizzazioni sono disattivate.
Se una funzione e' dichiarata inline in un'unita' di compilazione, il corpo deve essere definito in quell'unita'. Il comportamento del compilatore in relazione alla semantica del codice non deve cambiare a seconda delle ottimizzazioni.
Ecco a me è proprio questo che non torna. Ok, ho sbagliato a mettere il corpo della funzione inline non nell'header. Ma se non mettevo il flag -O2 non me ne sarei mai accorto!!
Anche icc della Intel ha lo stesso comportamento. Mi pare strano che due compilatori diversi hanno questo comportamento.
Hai un qualche profiling che dimostri che dichiarare quella funzione inline e' un'ottimizzazione misurabile oppure e' solo una tua ipotesi? :)
Non ho fatto questo controllo, ma una funzione chiamata qualche migliaio di volte, se non un milione di volte, e con un corpo di tre righe di codice.. beh se il compilatore non mette inline quella, allora credo che non ne metta mai nessuna :)
Ecco a me è proprio questo che non torna. Ok, ho sbagliato a mettere il corpo della funzione inline non nell'header. Ma se non mettevo il flag -O2 non me ne sarei mai accorto!!
Anche icc della Intel ha lo stesso comportamento. Mi pare strano che due compilatori diversi hanno questo comportamento.
Ho provato per curiosita' con VS2005 e VS2008 ed entrambi danno correttamente l'errore anche senza ottimizzazioni attivate.
Curioso.
Comunque, non dichiarare quella funzione inline, tanto se il compilatore e' decente, nel 99.99% dei casi non cambia nulla a livello prestazionale :)
Non ho fatto questo controllo, ma una funzione chiamata qualche migliaio di volte, se non un milione di volte, e con un corpo di tre righe di codice.. beh se il compilatore non mette inline quella, allora credo che non ne metta mai nessuna :)
Guarda, ti puo' stupire la cosa, ma un buon compilatore quando conviene te la mette inline anche se non la dichiari inline (Whole Program Optimization).
In generale non dichiarare mai una funzione inline se non hai veramente un buon motivo per farlo, e solo dopo che hai provato empiricamente che mettere quella funzione inline ti dia effettivamente un guadagno.
Ancora piu' in generale, non fare mai assunzioni sulle ottimizzazioni, perche' scoprirai che nella maggior parte dei casi la tua assunzione e' sbagliata, spesso e volentieri quelle che pensiamo essere ottimizzazioni sono pessimizzazioni!
Che succede, ad esempio, se mettere una funzione inline ti causa frequenti cache miss in un loop e il codice va in realta' piu' piano? Non puoi saperlo finche' non misuri.
Mentre dichiarare una funzione online porta sicuramente degli svantaggi a livello di gestione del progetto. Innanzitutto ci hai gia' perso del tempo :)
Poi dichiarare metodi inline significa che ti devi portare eventualmente dietro nell'header file la dichiarazione di ogni eventuale oggetto che quella funzione usa. Poi, se dichiari un metodo virtuale inline carichi di moltissimo lavoro il linker. Ho visto situazioni in progetti grossi nelle quali togliere la dichiarazione inline da un metodo ha fatto scendere il tempo di link di minuti!
Visto che più o meno sino in tema, vorrei proporre altri quesiti.
Vorrei forzare una funzione ad essere inline, però ha circa 20 righe di codice. Anche questa è richiamata spessissimo. Quale è il flag di g++ che fa questo ? Non lo trovo più.
Inoltre, a parte l'aumento di spazio dell'eseguibile, quali contro indicazioni ci sono a forzare un inlining?
Ed inoltre, quale era quel flag che faceva vedere se il g++ ha messo o no inline una funzione? Grazie
Ho provato per curiosita' con VS2005 e VS2008 ed entrambi danno correttamente l'errore anche senza ottimizzazioni attivate.
Curioso.
Comunque, non dichiarare quella funzione inline, tanto se il compilatore e' decente, nel 99.99% dei casi non cambia nulla a livello prestazionale :)
No aspetta, intendi dire che lo fa comunque l'inlining? Perchè altrimenti ho l'overhead della chiamata a funzione, e non sarebbe sicuramente la stessa cosa a livello di prestazioni.
Vorrei forzare una funzione ad essere inline, però ha circa 20 righe di codice. Anche questa è richiamata spessissimo. Quale è il flag di g++ che fa questo ? Non lo trovo più.
Se una funzione e' lunga, e' altamente probabile che anche forzando l'inline il compilatore lo ignori. Non perdere tempo e non dichiarare nulla inline, il tuo codice ti ringraziera', e molto probabilmente scoprirai che l'eseguibile risulta anche piu' veloce. Male che ti vada non cambia nulla.
Che succede, ad esempio, se mettere una funzione inline ti causa frequenti cache miss in un loop e il codice va in realta' piu' piano? Non puoi saperlo finche' non misuri.
Mmm, ai cache miss non ci avevo pensato. Però penso basti fare un pò di prove no ?
Se una funzione e' lunga, e' altamente probabile che anche forzando l'inline il compilatore lo ignori. Non perdere tempo e non dichiarare nulla inline, il tuo codice ti ringraziera', e molto probabilmente scoprirai che l'eseguibile risulta anche piu' veloce. Male che ti vada non cambia nulla.
Non lo so, però dichiarando un pò di funzioni inline e con il flag -O2 il codice va 3 volte più veloce !
E poi, quando una funzione è da considerarsi "lunga" per l'inline ? Questa cosa non l'ho mai capita.:confused:
Mmm, ai cache miss non ci avevo pensato. Però penso basti fare un pò di prove no ?
Si', e' quello che ti dicevo :)
Prima fai le prove, fai il profiling, poi se proprio scopri he una funzione serve inline, dichiarala inline. Almeno io faccio cosi', non dichiaro mai nulla inline, poi se il profiler mi dice che una data funzione molto piccola mi sta portando via del tempo perche' il compilatore per qualche motivo ha deciso di non metterla inline da solo, allora, la forzo io. Negli ultimi cinque anni ho dichiarato inline... hmmm... forse due funzioni.
Si', e' quello che ti dicevo :)
Prima fai le prove, fai il profiling, poi se proprio scopri he una funzione serve inline, dichiarala inline. Almeno io faccio cosi', non dichiaro mai nulla inline, poi se il profiler mi dice che una data funzione molto piccola mi sta portando via del tempo perche' il compilatore per qualche motivo ha deciso di non metterla inline da solo, allora, la forzo io. Negli ultimi cinque anni ho dichiarato inline... hmmm... forse due funzioni.
Però nel mio caso direi che ha fatto più che bene metterle inline. Il codice va 3 volte più veloce, e non penso dipenda solo dal flag -02
Non lo so, però dichiarando un pò di funzioni inline e con il flag -O2 il codice va 3 volte più veloce !
Lo hai misurato? Hai messo TUTTE le ottimizzazioni al massimo? Anche le ottimizzazioni globali? I compilatori moderni sono in grado di andare a "sbirciare" la definizione di una funzione anche al di fuori dell'unita di compilazione corrente e se decidono, in base a euristiche loro, che una funzione e' abbastanza piccola, la mettono inline comunque.
E poi, quando una funzione è da considerarsi "lunga" per l'inline ? Questa cosa non l'ho mai capita.:confused:
Dipende da compilatore a compilatore.
Lo hai misurato? Hai messo TUTTE le ottimizzazioni al massimo? Anche le ottimizzazioni globali?
Ho messo : senza ottimizzazioni,poi con -02 e poi con -02 ed inlining, ed il risultato migliore è stato l'ultimo :)
Ho messo : senza ottimizzazioni,poi con -02 e poi con -02 ed inlining, ed il risultato migliore è stato l'ultimo :)
Cambia compilatore :D
Cambia compilatore :D
Non so che dirti, se vuoi farò test più accurati. Uso g++, non è proprio un compilatore scadente :)
Non so che dirti, se vuoi farò test più accurati. Uso g++, non è proprio un compilatore scadente :)
Prova con il compilatore Intel, di solito e' ottimo.
Con il compilatore MS si usa questa opzione:
http://msdn2.microsoft.com/en-us/library/0zza0de8(VS.71).aspx
With information on all modules, the compiler can:
- Optimize the use of registers across function boundaries.
- Inline a function in a module even when the function is defined in another module.
Beh sai, forse il fatto è che il programma è parallelo, quindi secondo me il discorso cambia molto.
Con -O3 hai provato ?
-O3 ho un pò di paura ad usarlo. Non vorrei che mi cambiassero i risultati a causa dell'ottimizzazione troppo spinta.
Intanto prova e poi verifica ;)
-O3 Optimize yet more. -O3 turns on all optimizations specified by -O2
and also turns on the -finline-functions, -funswitch-loops and
-fgcse-after-reload options.
-finline-functions
Integrate all simple functions into their callers. The compiler
heuristically decides which functions are simple enough to be worth
integrating in this way.
If all calls to a given function are integrated, and the function
is declared "static", then the function is normally not output as
assembler code in its own right.
Intanto prova e poi verifica ;)
-O3 Optimize yet more. -O3 turns on all optimizations specified by -O2
and also turns on the -finline-functions, -funswitch-loops and
-fgcse-after-reload options.
-finline-functions
Integrate all simple functions into their callers. The compiler
heuristically decides which functions are simple enough to be worth
integrating in this way.
If all calls to a given function are integrated, and the function
is declared "static", then the function is normally not output as
assembler code in its own right.
Eh, lo so. Però questo programma gira su decine di processori per ore, non basta fare una prova di due minuti :) Comunque prima o poi lo proverò, ma per adesso preferisco di no. PS:te lo sai il flag per sapere quali funzioni il compilatore ha messo inline? Non mi riesce trovarlo !
Ma l'opzione a cui si riferisce fek qui:
I compilatori moderni sono in grado di andare a "sbirciare" la definizione di una funzione anche al di fuori dell'unita di compilazione corrente e se decidono, in base a euristiche loro, che una funzione e' abbastanza piccola, la mettono inline comunque.
E' -finline-functions...se te abiliti questa opzione e non il resto delle ottimizzazioni O3 dovresti andare sul sicuro.
ilsensine
20-12-2007, 15:36
Però nel mio caso direi che ha fatto più che bene metterle inline. Il codice va 3 volte più veloce, e non penso dipenda solo dal flag -02
Non è il comportamento corretto, "inline" non fa quello che pensi. Almeno non con un g++ decentemente recente.
Il compilatore è libero di mettere inline anche le funzioni che non dichiari come inline se ritiene opportuno, come è libero di mettere out-of-line le funzioni dichiarate "inline". Quindi, in sintesi, inline è in genere inutile (a parte negli header, ma per motivi diversi).
In genere l'euristica del compilatore funziona bene, forse nel tuo caso ha ciccato per qualche motivo.
ilsensine
20-12-2007, 15:40
E' -finline-functions...se te abiliti questa opzione e non il resto delle ottimizzazioni O3 dovresti andare sul sicuro.
Hai ragione, errore mio...credevo che già O2 avesse -finline-functions. QUesto potrebbe spiegare la differenza.
Hai ragione, errore mio...credevo che già O2 avesse -finline-functions. QUesto potrebbe spiegare la differenza.
Perfetto, allora non gli serve neppure cambiare compilatore. Curiosita' mia, c'e' qualcosa tipo Profile-Guided-Optimization in g++?
Non è il comportamento corretto, "inline" non fa quello che pensi. Almeno non con un g++ decentemente recente.
Il compilatore è libero di mettere inline anche le funzioni che non dichiari come inline se ritiene opportuno, come è libero di mettere out-of-line le funzioni dichiarate "inline". Quindi, in sintesi, inline è in genere inutile (a parte negli header, ma per motivi diversi).
In genere l'euristica del compilatore funziona bene, forse nel tuo caso ha ciccato per qualche motivo.
Secondo me il discorso è più complicato essendo il programma parallelo. Per questo appare il comportamento strano che ho rilevato.
ilsensine
20-12-2007, 15:58
Perfetto, allora non gli serve neppure cambiare compilatore. Curiosita' mia, c'e' qualcosa tipo Profile-Guided-Optimization in g++?
Sì ci sono questi due switch:
`-fprofile-generate'
Enable options usually used for instrumenting application to
produce profile useful for later recompilation with profile
feedback based optimization. You must use `-fprofile-generate'
both when compiling and when linking your program.
The following options are enabled: `-fprofile-arcs',
`-fprofile-values', `-fvpt'.
`-fprofile-use'
Enable profile feedback directed optimizations, and optimizations
generally profitable only with profile feedback available.
The following options are enabled: `-fbranch-probabilities',
`-fvpt', `-funroll-loops', `-fpeel-loops', `-ftracer',
`-fno-loop-optimize'.
Sì ci sono questi due switch:
`-fprofile-generate'
Enable options usually used for instrumenting application to
produce profile useful for later recompilation with profile
feedback based optimization. You must use `-fprofile-generate'
both when compiling and when linking your program.
The following options are enabled: `-fprofile-arcs',
`-fprofile-values', `-fvpt'.
`-fprofile-use'
Enable profile feedback directed optimizations, and optimizations
generally profitable only with profile feedback available.
The following options are enabled: `-fbranch-probabilities',
`-fvpt', `-funroll-loops', `-fpeel-loops', `-ftracer',
`-fno-loop-optimize'.
Bingo, sono loro :)
Continuando il profiling del codice, ho scoperto un'altra cosa molto strana. Se non uso ottimizzazioni, tutto funziona liscio a runtime. Se ottimizzo con -O2, mi dà un SIG FAULT in esecuzione in un punto di codice che ho aggiunto! Questo con g++ 4.0
Passando ad un altra versione del compilatore, il g++ 3.4, anche con -O2 non ho problemi. Sicuramente il codice va bene, in quanto senza ottimizzazioni funziona regolarmente. Funziona bene anche con -O1. In questo caso, il compilatore fa qualche aggiustamento che comporta un Segmentation Fault. Davvero molto strano.
^TiGeRShArK^
23-12-2007, 11:50
Continuando il profiling del codice, ho scoperto un'altra cosa molto strana. Se non uso ottimizzazioni, tutto funziona liscio a runtime. Se ottimizzo con -O2, mi dà un SIG FAULT in esecuzione in un punto di codice che ho aggiunto! Questo con g++ 4.0
Passando ad un altra versione del compilatore, il g++ 3.4, anche con -O2 non ho problemi. Sicuramente il codice va bene, in quanto senza ottimizzazioni funziona regolarmente. Funziona bene anche con -O1. In questo caso, il compilatore fa qualche aggiustamento che comporta un Segmentation Fault. Davvero molto strano.
ah..la bellezza del C++ :asd:
Imho è un bug relativo alla memoria...è sintomatico il fatto che non avvenga con tutte le varie ottimizzazioni.
ah..la bellezza del C++ :asd:
Che c'entra il c++, è il compilatore...
Tra l'altro se sta usando MinGW, la versione 4 è un Tecnology Preview...
Imho è un bug relativo alla memoria...è sintomatico il fatto che non avvenga con tutte le varie ottimizzazioni.
Direi proprio di si. Nel mio codice faccio un pesante uso di puntatori tripli e quadrupli. Secondo me si inceppa il meccanismo di ottimizzazione del compilatore. Infatti sto pensando di linearizzare tutte le matrici, così non avrò più questi problemi ed il codice andrà molto più veloce :) Anche se, non essendo le matrici regolari, mi ci vorrà un pò di tempo :(
Ragazzi, non ci sto capendo più niente! Ho cambiato compilatore, passando a icc della Intel. Con l'ottimizzazione -O1 adesso addirittura a runtime, dopo un pò, mi scappano fuori i Not a Number !!
Comincio a pensare che in caso di matrici di 4 dimensioni è bene NON usare ottimizzazioni. :(
Comincio a pensare che in caso di matrici di 4 dimensioni è bene NON usare ottimizzazioni. :(
Ma a questo punto non è un problema di ottimizzazioni, ma è qualche bug del codice che con le ottimizzazioni viene fuori più facilmente ;)
Non credo, mai venuti fuori Not A Number senza ottimizzazioni, anche dopo 20 ore di esecuzione.
Trallaltro, g++ li fa venire fuori dopo un'ora di calcoli, icc dopo 15 minuti. Ho controllato i risultati parziali poco prima che si bloccasse tutto, ed erano ben diversi con i risultati parziali senza ottimizzazione! Se i conti vengono diversi, è l'ottimizzazione che cicca. Ho usato un debugger , DDT, che non ha rilevato anomalie. Il programma è stato eseguito normalmente. Mi sembra improbabile che il mio codice abbia un bug che neanche un debugger rilevi.
La riga di codice incriminata, lavora su una matrice di tre dimensioni. Siccome prima, con ottimizzazioni, mi dava SIG FAULT senza motivo con il gcc 3.4, allora sono ritenuto a pensare che dia anche i Nan senza motivo :)
Anzi, ricontrollando il codice, sono ancora più convinto che dipenda dalle ottimizzazioni e vi spiego perchè: nella riga incriminata, si accede ad una matrice di 3 dimensioni. Tale riga è dentro un ciclo for. Nello stesso ciclo, ho un'altra matrice di 3 dimensioni che ha esattamente le stesse dimensioni della precedente, e ci accedo con gli stessi indici.
Ora, se per esempio fosse un problema di indici, mi darebbe i Nan anche senza la riga incriminata. Qualunque bug che coinvolga la prima matrice, dovrebbe coinvolgere anche la seconda, in quanto l'allocazione e l'accesso avviene allo stesso modo. Se volete vi posto il pezzo di codice.
No, la mia idea è diversa.
Un buffer overflow o qualcosa del genere che con le ottimizzazioni si presente più facilmente. Il fatto che non si pianti mai senza ottimizzazioni non implica che non ci sia il buffer overflow.
Basta una cazzata...ad esempio una stringa con spazio non allocato e magari un "pack" diverso utilizzato da una struttura dati con le ottimizzazioni, ed ecco che il bug ti si presenta con le ottimizzazioni e non senza.
In ogni caso le ottimizzazioni sono state studia per poter essere applicate sempre...cioè dovrebbero essere come un refactoring del codice assembly generato, quindi agli effetti esterni le istruzioni modificate dalle ottimizzazioni devono essere assolutamente trasparenti. Se ti si pianta con le ottimizzazioni, con due compilatori diversi tra l'altro, allora c'è un bug, imho credo non ci siano alternative.
No, la mia idea è diversa.
Un buffer overflow o qualcosa del genere che con le ottimizzazioni si presente più facilmente. Il fatto che non si pianti mai senza ottimizzazioni non implica che non ci sia il buffer overflow.
Basta una cazzata...ad esempio una stringa con spazio non allocato e magari un "pack" diverso utilizzato da una struttura dati con le ottimizzazioni, ed ecco che il bug ti si presenta con le ottimizzazioni e non senza.
In ogni caso le ottimizzazioni sono state studia per poter essere applicate sempre...cioè dovrebbero essere come un refactoring del codice assembly generato, quindi agli effetti esterni le istruzioni modificate dalle ottimizzazioni devono essere assolutamente trasparenti. Se ti si pianta con le ottimizzazioni, con due compilatori diversi tra l'altro, allora c'è un bug, imho credo non ci siano alternative.
Supponiamo che ci sia un bug nel mio codice, ok. Però come si spiegano i risultati parziali diversi? Se le modifiche del compilatore causano risultati diversi, allora non sono trasparenti. Io sapevo che con le varie ottimizzazioni, si deve stare attenti ad usarle proprio perchè con alcuni codici sono rischiose. Altrimenti si compilerebbe sempre e solo con -O3 no ? :)
Le varie ottimizzazioni ti possono cambiare i risultati parziali. In questo caso , anche un NaN può essere visto come un cambio di risultato. E poi, come è possibile che il debugger non le rilevi ? Forse perchè devo usarlo senza ottimizzazioni? Ma allora non riesco mai a presentare il caso anomalo :(
Altrimenti si compilerebbe sempre e solo con -O3 no ? :)
No...perché le ottimizzazioni hanno un costo in grandezza del codice, difficoltà di debugging, aumento del tempo di compilazione e spazio di memoria utilizzato. Inoltre non sempre le ottimizzazioni portano ad un incremento di prestazioni.
Si certo, ma soprattutto, in alcuni casi ottimizzazioni troppo spinte sono rischiose, proprio perchè il risultato finale può essere imprevedibile :)
Comunque anche io mi sto orientando su un buffer overflow. Se fosse un problema di accessi alle matrici, lo avrei ben prima questo problema, non dopo diverse iterazioni, in quanto vi accedo allo stesso modo in svariate parti del codice.
proprio perchè il risultato finale può essere imprevedibile :)
Sinceramente questo non l'ho mai letto da nessuna parte...ho anche cercato in giro, ma non ho trovato niente di questo tipo.
Le ottimizzazioni non devono essere rischiose...devono essere equivalenti ai fine esterni (per esterni intendo a livello della singola istruzioni C++) al codice originale, se non lo sono il compilatore è buggato.
Sinceramente questo non l'ho mai letto da nessuna parte...ho anche cercato in giro, ma non ho trovato niente di questo tipo.
Le ottimizzazioni non devono essere rischiose...devono essere equivalenti ai fine esterni (per esterni intendo a livello della singola istruzioni C++) al codice originale, se non lo sono il compilatore è buggato.
Per imprevedibile intendo con risultati diversi. Ho sentito persone che lavorano con applicazioni parallele che mi hanno confermato il fatto che, le varie ottimizzazioni, possono cambiare i risultati parziali. C'è da tenere conto che ci sono chiamate parallele nel mezzo, vai a sapere che combina l'euristica del compilatore lì dentro..
Io confermo che è un buffer underflow. Cambiando alcuni parametri troppo piccoli, il problema per adesso non si è ripresentato. Neanche con -O3 . Se fosse un problema di accesso alla matrice, me lo darebbe molto prima, non dopo 10.000 epoche. Ad ogni epoca infatti, il programma rifà esattamente gli stessi passi dell'epoca precedente. L'unica cosa che cambia sono i pesi della rete, che , effettivamente, potrebbero andare in underflow.
^TiGeRShArK^
24-12-2007, 13:31
Che c'entra il c++, è il compilatore...
Tra l'altro se sta usando MinGW, la versione 4 è un Tecnology Preview...
Io confermo che è un buffer underflow. Cambiando alcuni parametri troppo piccoli, il problema per adesso non si è ripresentato. Neanche con -O3 . Se fosse un problema di accesso alla matrice, me lo darebbe molto prima, non dopo 10.000 epoche. Ad ogni epoca infatti, il programma rifà esattamente gli stessi passi dell'epoca precedente. L'unica cosa che cambia sono i pesi della rete, che , effettivamente, potrebbero andare in underflow.
ah..la bellezza del C++ :asd:
;)
Non ho capito questa risposta.. Un buffer underflow non è colpa del compilatore o del linguaggio, ma di quello che fa l'applicazione. Comunque sono sotto Linux, non Windows.
^TiGeRShArK^
24-12-2007, 14:04
Non ho capito questa risposta.. Un buffer underflow non è colpa del compilatore o del linguaggio, ma di quello che fa l'applicazione. Comunque sono sotto Linux, non Windows.
errori nella gestione della memoria sono comunissimi in linguaggi come il C++.
In java, ad esempio, un errore del genere sarebbe dipeso solo da un bug della JVM o dall'utilizzo di librerie native.
Certo..
ci sono sempre gli errori logici e di threading in agguato..
ma sinceramente già eliminare i segmentation fault è imho un bel passo avanti :p
No ma scusa, un buffer overflow o underflow non è un errore di gestione della memoria, almeno non nel mio caso. Quando hai molte moltiplicazioni tra double, è sempre in agguato questo problema.
^TiGeRShArK^
24-12-2007, 14:29
No ma scusa, un buffer overflow o underflow non è un errore di gestione della memoria, almeno non nel mio caso. Quando hai molte moltiplicazioni tra double, è sempre in agguato questo problema.
:mbe:
perchè?
un buffer overflow è per definizione quando accedi ad aree di memoria al di fuori dei limiti di un buffer a dimensione fissa.
..quindi..
o tu intendi un'altra cosa per buffer overflow o c'è qualcosa che mi sfugge :mbe:
sinceramente i segmentation fault io li ho visti sempre per problemi di gestione della memoria, anche perchè è per definizione un problema relativo all'accesso di memoria a cui non dovrebbe essere permesso accedere.
E problemi del genere in linguaggi che hanno un memory manager che si occupa della gestione automatica delle risorse, che io sappia, non possono accadere, a meno, come dicevo prima di bug del memory manager o di librerie native.
Quindi..
a questo punto..
che intendi per segmentation fault e per buffer underflow? :fagiano:
Il mio problema è che il numero double può essere più piccolo del più piccolo numero rappresentabile dalla macchina. Non è un buffer underflow questo? Mi pare di si..
^TiGeRShArK^
24-12-2007, 14:41
Il mio problema è che il numero double può essere più piccolo del più piccolo numero rappresentabile dalla macchina. Non è un buffer underflow questo?
ehmm..
no :fagiano:
da che io ricordi quello viene chiamato Arithmetic underflow, non buffer underflow.
E cmq in effetti gli effetti dell'underflow dipendono dal SO su cui gira il programma..
certo che un segmentation fault mi pare strano :mbe:
quello è di sicuro un errore di memoria, quindi, così ad occhio, direi che l'underflow genera degli effetti collaterali che poi generano a loro volta un segmentation fault, anche perchè solitamente l'arithmetic underflow genera questi effetti (presi da wikipedia perchè sinceramente non li ricordo tutti a memoria :fagiano: )
Depending on the processor, the programming language and the run-time system, underflow may set a status bit, raise an exception, generate a hardware interrupt, or may cause some combination of these effects. Alternatively, the underflow may just be ignored and zero substituted for the unrepresentable value, although this might lead to a later division by zero error which cannot be so easily ignored.
As specified in IEEE 754 the underflow condition is only signalled if there is also a loss of accuracy. Typically this is determined as the final result being inexact. However if the user is trapping on underflow, this may happen regardless of consideration for loss of precision.
Il mio problema è che il numero double può essere più piccolo del più piccolo numero rappresentabile dalla macchina. Non è un buffer underflow questo? Mi pare di si..
No...è un errore di rappresentazione.
Buffer underflow: http://en.wikipedia.org/wiki/Buffer_underrun
Buffer overflow: http://en.wikipedia.org/wiki/Buffer_overflow
Ah ok, mi sono confuso :D
Beh, resta il fatto che ,almeno per adesso, mettendo dei controlli opportuni non ho più visto Nan. Speriamo bene..
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.