Ottimizzare eseguibile affinchè giri più rapidamente

Forum dedicato alla programmazione.

Moderatore: Staff

Regole del forum
1) Citare in modo preciso il linguaggio di programmazione usato.
2) Se possibile portare un esempio del risultato atteso.
3) Leggere attentamente le risposte ricevute.
4) Scrivere i messaggi con il colore di default, evitare altri colori.
5) Scrivere in Italiano o in Inglese, se possibile grammaticalmente corretto, evitate stili di scrittura poco chiari, quindi nessuna abbreviazione tipo telegramma o scrittura stile SMS o CHAT.
6) Appena registrati è consigliato presentarsi nel forum dedicato.

La non osservanza delle regole porta a provvedimenti di vari tipo da parte dello staff, in particolare la non osservanza della regola 5 porta alla cancellazione del post e alla segnalazione dell'utente. In caso di recidività l'utente rischia il ban temporaneo.
Avatar utente
joe
Iper Master
Iper Master
Messaggi: 3790
Iscritto il: ven 27 apr 2007, 11:21
Slackware: 15.0
Kernel: 5.15.38
Desktop: dwm

Ottimizzare eseguibile affinchè giri più rapidamente

Messaggio da joe »

Sono alle prese con un programma scritto in Fortran del quale vorrei ottimizzare un poco i tempi di esecuzione.
È un programma scritto ancora su base fortran 77 che non ho fatto io e ha l'obiettivo di trovare il migliore set di parametri per descrivere un fenomeno fisico del quale si è costruito un modello matematico. Insomma un gran minestrone di formule (neanche troppo complesse) ecc, ma niente di trascendentale alla fine dal punto di vista del calcolo numerico.

In pratica si ha un grande loop e per ogni iterazione si variano un poco i valori dei parametri e si confronta il risultato che restituisce il modello matematico

- set di parametri di tentativo
- calcolo risultati introducendo i parametri di cui sopra in un modello matematico
- confronto delle grandezze risultanti con le stesse grandezze ma quelle reali misurate fisicamente calcolando lo "scarto quadratico medio" tra le due grandezze calcolate e misurate
- piccola variazione dei valori dei parametri di tentativo
- riparte il ciclo

Ad ogni ciclo si ha un nuovo valore dello scarto quadratico medio e il nuovo set di parametri è migliore del precedente se porta ad un "sqm" inferiore.

Sta roba può girare per ore, giorni, mesi e così via...
Ovviamente il tutto finisce quando si ritiene che il modello così "tarato" descriva la realtà in modo soddisfacente.

Ok, tutta sta spiegazione per chiedere. Come si può compilare il sorgente per ottimizzare l'eseguibile in modo che giri più rapidamente su di un PC moderno?
Ad esempio io ho provato 2 cose:
  1. Compilare con l'opzione "-O2":

    Codice: Seleziona tutto

    gfortran -O2 sorgente.f
  2. Escludere la scrittura dei risultati su Hard Disk lavorando da una directory montata in RAM
Me ne viene in mente un'altra:
Il programma scrive a video parecchia roba ad ogni ciclo... Potrebbe velocizzare parecchio modificare il sorgente affinchè non scriva nulla a schermo?

Altre cose che vi vengono in mente... così senza saperne troppa sul particolare programma.

Avatar utente
F4B1CK
Linux 2.x
Linux 2.x
Messaggi: 295
Iscritto il: dom 11 gen 2004, 0:00
Slackware: current 64 bit
Kernel: 5.14.x
Desktop: KDE PLASMA
Località: Cosenza
Contatta:

Re: Ottimizzare eseguibile affinchè giri più rapidamente

Messaggio da F4B1CK »

Ciao,
ti riporto l'esperienza di un amico che, essendo un ricercatore di fisica all'università, lavora molto con i software scritti in Fortran.
Loro si stanno orientando al calcolo parallelo, quindi vanno ad ottimizzare il codice fortran per lavorare su più core contemporaneamente, di modo da sfruttare tutta la potenza della macchina.
Tutto ciò si fà utilizzando delle librerie apposite ed alcune righe di codice aggiuntive per la gestione dei processi (credo che troverai molto materiale online a riguardo).
Addirittura mi diceva di voler sperimentare l'utilizzo delle GPU per il calcolo parallelo.
Potresti dare un'occhiata al materiale che trovi in rete a riguardo, ovviamente non so se tale tipo di ottimizzazione sia applicabile al tuo specifico caso.

In bocca al lupo!

Avatar utente
joe
Iper Master
Iper Master
Messaggi: 3790
Iscritto il: ven 27 apr 2007, 11:21
Slackware: 15.0
Kernel: 5.15.38
Desktop: dwm

Re: Ottimizzare eseguibile affinchè giri più rapidamente

Messaggio da joe »

Grazie delle informazioni.

Penso sempre che la maggior ottimizzazione sia da ricercarsi in primis nella nella stesura di un codice "più intelligente" della versione precedente, proprio in termini di organizzazione delle operazioni che fà il programma. Detto questo per andare oltre sarebbe davvero interessante applicare le diavolerie tecnologiche che citavi (paralizzazione, sfruttamento di hardware più efficiente).

Tornando a volare un po' più bassi, ho trovato leggendo la documentazione gnu che si può compilare così:

Codice: Seleziona tutto

gfortran -Ofast -march=native -fno-gcse
In questo modo si dovrebbe ottimizzare la velocità d'esecuzione dell'eseguibile e si impiega teoricamente di più in fase di compilazione (nel mio caso non è un problema perchè il codice è piuttosto semplice e la compilazione avviene in mezzo secondo...).

Ho provato, effettivamente ad occhi si và molto più rapidi, vengono fatte circa 100 reiterazioni del ciclo al secondo: molto meglio di prima.
Ma c'è un problema! Un grosso problema...
Il programma lavora con variabili in doppia precisione, quindi sono numeri con tante cifre dopo la virgola e tutte "piuttosto importanti".
Compilando il sorgente con le opzioni sopracitate l'eseguibile dà risultati strani!

In pratica a video vengono stampato un numero che è un risultato dell'iterazione corrente. Ad ogni iterazione viene stampato un valore diverso che tendenzialmente deve essere più basso del precedente. quindi a video mi aspetto una cosa del tipo:

Codice: Seleziona tutto

 valore=   4.8868482388357531E-002         403
 valore=   4.8868482332274164E-002         404
 valore=   4.8868482332218410E-002         405
 valore=   4.8868482323832681E-002         406
 valore=   4.8868481574640708E-002         407
 valore=   4.8868481547551954E-002         408
 valore=   4.8868481466771627E-002         409
Questo è quello che si ha compilando senza ottimizzazioni: l'eseguibile và piano ma dà risultati giusti.

Invece aggiungendo le opzioni di ottimizzazione ecco cosa accade:

Codice: Seleziona tutto

 valore=   4.8868888502700901E-002         403
 valore=   4.8868888502700901E-002         404
 valore=   4.8868888502700901E-002         405
 valore=   4.8868888502700901E-002         406
 valore=   4.8868888502700901E-002         407
 valore=   4.8868888502700901E-002         408
 valore=   4.8868888502700901E-002         409
In pratica viene stampato sempre lo stesso valore.
Questo dovrebbe essere impossibile, perchè nel programma c'è un'istruzione che termina l'esecuzione proprio nel caso in cui il valore del numero corrente è uguale a quello precedente.

Ora, la domanda che vi pongo è questa:
sapete perchè accade questo?
Come è possibile che le opzioni di ottimizzazione del gnu compiler vadano ad influenzare i valori delle variabili in doppia precisione?
E ancora c'è un modo per avere la moglie ubriaca e la botte piena, ovvero si può ottimizzare nel modo sopra aggiungendo una qualche opzione che preservi la doppia precisione delle variabili?

Grazie ancora della risposta F4B1CK! :D

Avatar utente
N1cuz
Linux 2.x
Linux 2.x
Messaggi: 333
Iscritto il: lun 6 ott 2008, 0:41
Nome Cognome: Nicola Bartolomei
Slackware: 14.1
Kernel: 4.3.3
Desktop: xfce4
Località: Pieve a Nievole (PT)

Re: Ottimizzare eseguibile affinchè giri più rapidamente

Messaggio da N1cuz »

Ciao, quoto quanto detto da F4B1CK, anche se la parallelizzazione non è una cosa così banale (a me non è ancora riuscito parallelizare il mio codice...), un'altra cosa da fare potrebbe essere rivedere il codice e capire se i passi del processo possono essere riscritti meglio (limitare le chiamate a funzione) ecc... Anche le scritte a video sono utili, ma senza esagerare perchè rallentano l'esecuzione.
Detto questo io compilo sempre con le opzioni

Codice: Seleziona tutto

gfortran -Ofast -march=native
E non mi da problemi sulla mia macchina. Devo invece ricompilare da sorgente se lo voglio eseguire su una macchina del lab.
Curiosità, le variabili reali le hai dichiarate semplicemente real o real(kind=8)????
P.S. Io aggiungerei pure:

Codice: Seleziona tutto

-g -Wall -fcheck=all
In boca al lupo!

Nicola

Avatar utente
joe
Iper Master
Iper Master
Messaggi: 3790
Iscritto il: ven 27 apr 2007, 11:21
Slackware: 15.0
Kernel: 5.15.38
Desktop: dwm

Re: Ottimizzare eseguibile affinchè giri più rapidamente

Messaggio da joe »

Guarda sono un po' arrugginito sulla sintassi, ma all'inizio del programma vedo che le variabili sono dichiarate come real*8 che penso sia la stessa cosa di real(kind=8)

Codice: Seleziona tutto

implicit real*8 (a-h,o-z)
Il fatto nel tuo caso di doverlo ricompilare su una macchina forse è dovuto all'opzione -march=native.
Proverò anche le opzioni che consigli.

Circa la parallelizzazione del codice. Non ne so nulla e infatti penso anch'io che non sia così banale.
Servirebbe capire come si parallelizza un "hello world", tanto per iniziare.
Oppure qualcosa di un po' più corposo del tipo:
- leggi 1000 numeri dal file 1, elaborali matematicamente (tipo moltiplicali per qualcosa) e sputa il risultato in un output_1
- leggi 1000 numeri diversi dal file 2, elaborali matematicamente (tipo moltiplicali per qualcosa) e sputa il risultato in un output_2
Già una cosa del genere ha l'aria più "parllelizzabile" :D
Cercherò qualcosa in merito.

Domandona da ignorante per gli esperti.
Perchè la scrittura a video rallenta il calcolo?

Avatar utente
N1cuz
Linux 2.x
Linux 2.x
Messaggi: 333
Iscritto il: lun 6 ott 2008, 0:41
Nome Cognome: Nicola Bartolomei
Slackware: 14.1
Kernel: 4.3.3
Desktop: xfce4
Località: Pieve a Nievole (PT)

Re: Ottimizzare eseguibile affinchè giri più rapidamente

Messaggio da N1cuz »

Si è la stessa cosa, kind mi pare che sia da fortran 95 in poi, mentre il tuo codice è in fortran 77, comunque è possibile che -Ofast sia eccessivo (mi pare di aver letto che corrisponde a -O3) di solito -O2 è già buono.
Per quanto riguarda la scrittura a video il tempo impiegato a stampare può essere trascurabile rispetto al programma, se nel tuo ciclo hai una chiamata

Codice: Seleziona tutto

write(*,*)
oppure nel tuo caso

Codice: Seleziona tutto

print*
che stampa a video il risultato parziale della tua formula che mi pare di capire sia un numero reale allora è così (se provi a commentare il print ti rendi conto che non cambia nulla), se invece i tuoi risultati parziali sono matrici piuttosto grandi ad ogni ciclo deve stampare a video migliaia di valori è ovvio che allora il tempo di esecuzione aumenta.... Comunque per rendertene conto puoi far stampare a video il tempo di esecuzione dei vari blocchi di codice così ti rendi conto dove ha senso mettere le mani.

Nico

Avatar utente
joe
Iper Master
Iper Master
Messaggi: 3790
Iscritto il: ven 27 apr 2007, 11:21
Slackware: 15.0
Kernel: 5.15.38
Desktop: dwm

Re: Ottimizzare eseguibile affinchè giri più rapidamente

Messaggio da joe »

Ho provato anche con il solo "-O2". Le prestazioni sono comparabili ad -Ofast.
I risultati purtroppo anche, cioè quei numeroni sopra non decrescono, stampa sempre la stessa cifra.

La scrittura a video è del tipo write e la variabile è il numero che vedi sopra quindi sì un reale di 8 cifre:

Codice: Seleziona tutto

write(6,*) 'var = ',var
Sto cercando con scarsi risultati una corrispondenza nel manuale tra le opzioni di ottimizzazione e i numeri in precisione "8".
Mi viene qualche altro dubbio, del tipo:
mettiamo che nel programma si facciano operazioni che coinvolgano variabili diverse, non è che magari compilando senza ottimizzazioni, i risultati di operazioni matematiche prendono la precisione del numero con più cifre, mentre compilando con ottimizzazioni si ha una sorta di "cutting" e la precisione dei risultati alla fine risulta inferiore?

Tra l'altro ho capito perchè non si esce dal ciclo nonostante il risultato corrente sia identico a quello dello step precedente:

Codice: Seleziona tutto

if(var.lt.varmin) then
Ora provo a metterci "le" (less equal) e vediamo cosa fa.
Grazie dei commenti, se vi viene in mente qualcos'altro dite pure.
Appena risolvo, se risolvo vi faccio sapere come và a finire.

Avatar utente
N1cuz
Linux 2.x
Linux 2.x
Messaggi: 333
Iscritto il: lun 6 ott 2008, 0:41
Nome Cognome: Nicola Bartolomei
Slackware: 14.1
Kernel: 4.3.3
Desktop: xfce4
Località: Pieve a Nievole (PT)

Re: Ottimizzare eseguibile affinchè giri più rapidamente

Messaggio da N1cuz »

Se le operazioni intermedie coinvolgono tipi diversi può succedere che un real ti diventa un integer da qualche parte o qualche conversione che non è come ti aspetti, ma questo è indipendente dall'ottimizzazione e dovresti ottenere lo stesso risultato anche senza -O.
Le opzioni

Codice: Seleziona tutto

-g -Wall

Ti aiutano per vedere se da qualche parte viene assegnato un tipo ad un altro.


Mi viene in mente che in fortran devi stare attento alle divisioni, tipo:

Codice: Seleziona tutto

integer :: a=3
real*8 :: b

b=a/2   ! b=0.0
b=a/2.   ! b=1.5
Un'altra cosa che mi viene in mente ma che nel tuo caso credo serva a poco è che per uscire dai cicli è meglio

Codice: Seleziona tutto

if(abs(var-varmin).le.eps2) then
Ad ogni modo anche questo non dipende dal'ottimizzazione.... Sei sicuro al 100% che il codice sia corretto???
Te lo dico perchè personalmente mi è capitato di perdere un sacco di tempo per errori veramente stupidi, comunque io sono molto distratto e tendente a far cazzate quindi non faccio testo... In bocca al lupo! :)

Avatar utente
joe
Iper Master
Iper Master
Messaggi: 3790
Iscritto il: ven 27 apr 2007, 11:21
Slackware: 15.0
Kernel: 5.15.38
Desktop: dwm

Re: Ottimizzare eseguibile affinchè giri più rapidamente

Messaggio da joe »

Il sorgente non l'ho scritto io.
Quindi la sicurezza matematica che sia corretto al 100% non ce l'ho. Però è un programma utilizzato da tempo in un dipartimento universitario, quindi diciamo che me ne sto... Non è stato scritto da uno sviluppatore informatico ma da ing.
Che non mi convince troppo è la struttura un po' "arcaica" e come si interfaccia all'utente, infatti a me piacerebbe che girasse completamente in modo maggiormente autonomo: file di configurazione, running e stop. Può essere che si possa un attimo modernizzare e soprattutto ottimizzare riscrivendolo. Ovviamente la priorità è la correttezza dei risultati, questo è pacifico.

Ho in mente di riscriverlo, ma al momento devo dare priorità all'utilizzo del programma per produrre risultati, grafici e altre cose. Insomma, non ho troppo tempo per riscrivere tutto adesso. Però penso di farlo quanto prima, anche perchè immagino che mi sia necessario modificare il programma in conseguenza alla modifica di un modello fisico-matematico che ci stà dietro...
È ovvio che il risultato poi lo produce quel programma ed è abbastanza importante che sia ottimizzato per ridurre quanto più i tempi per raggiungere qualcosa di soddisfacente.

Il fatto che il sorgente sia corretto, nel senso che genera un eseguibile che a sua volta produce risultati giusti... bè su questo non ci piove.
Abbiamo confrontato i risultati dell'eseguibile compilato con:
1- gfortran senza opzioni di ottimizzazione.
2- ifort senza opzioni anche quello

Entrambi portano al risultato atteso, cioè il programma gira e gira, ad ogni giro quel valore di cui sopra cala costantemente. Se non cala il programma richiede all'utente un'azione che non sto a spiegare nel dettaglio, diciamo che esce dal ciclo insomma.
Aspetti notati: l'eseguibile compilato col compilatore intel "ifort" è decisamente più rapida, pur producendo risultati corretti. Personalmente no dispongo di quel compilatore e preferirei comunque arrangiarmi con quello GNU.

Insomma la correttezza dei risultati e il comportamento dell'eseguibile in termini di numeri sputati fuori deve essere corretto.

Altra cosa la condizione di uscita che dicevo al post recedente non è quella che avevo indicato.... Non è così banale diciamo.

Insomma, secondo me si tratta solo di capire quali opzioni di gfortran vengono raggruppate col flag "-O2" e tra quelle, quale fa a pugni con i numeri reali double precision...

Avatar utente
N1cuz
Linux 2.x
Linux 2.x
Messaggi: 333
Iscritto il: lun 6 ott 2008, 0:41
Nome Cognome: Nicola Bartolomei
Slackware: 14.1
Kernel: 4.3.3
Desktop: xfce4
Località: Pieve a Nievole (PT)

Re: Ottimizzare eseguibile affinchè giri più rapidamente

Messaggio da N1cuz »

Se lo utilizzano da tanto sarà ben testato, sicuramente finziona, poi che il codice sia scritto male è quasi una certezza se lo ha scritto un ingegnere :D, se un'informatico guarda il mio codice gli viene da vomitare di sicuro, d'altra parte è giusto che uno si occupi di buttare giù un codice anche rozzo che sia ottimizzato dal punto di vista dell'approccio matematico del problema e poi ci vuole un'informatico che ottimizzi il codice... Se uno riesce a far tutto da solo bon per lui, lo invidio!

Per quel che riguarda l'ifort è probabile che sia meglio del gfortran, onestamente non posso fare paragoni perchè il gfortran ce l'ho sul mio portatile, mentre il compilatore intel è sulla macchina del laboratorio quindi non è un confronto possibile, ora mi verrebbe da chiederti se avete provato a compilare con -O2 con l'ifort, se l risultato rimane stabile con l'ifort e magari è il gfortran che va in crisi ad ottimizzare con il fortran77.
Io sinceramente in fortran77 ho compilato solo un set di funzioni della libreria slatec mi pare per gestire le funzioni di bessel, per il resto il codice che ho scritto io è in fortran90 e con -O2 non ho mai avuto problemi (uso sia reali che complessi nel codice)....

Comunque secondo me che faccia cose strane coi reali mi sembra improbabile (ora provo a guardare che flag imposta -O2), ma è possibile che faccia casino nel ciclo (tipo come quando parallelizzi) che ti esegue un'operazione prima di un'altra o roba simile????

P.S. Sono parecchio interessato a questo topic perché è da due anni che uso il fortran e non sono molto esperto quindi ogni occasione è buona per imparare qualcosa :D

Avatar utente
joe
Iper Master
Iper Master
Messaggi: 3790
Iscritto il: ven 27 apr 2007, 11:21
Slackware: 15.0
Kernel: 5.15.38
Desktop: dwm

Re: Ottimizzare eseguibile affinchè giri più rapidamente

Messaggio da joe »

Bene, anche io ho imparato un po' di fortran in passato... alla fine ne avevo studiato i fondamenti su un testo che mi pare fosse il Chapman. Era fatto bene per chi non è un informatico ed era pensato ormai per fortran 90/95.
Tuttavia ai tempi non ero mai entrato nei dettagli della compilazione con opzioni particolari, ottimizzazione codice (parallelizzazione ecc). Alla fine i programmi con cui ho avuto a che fare erano e sono piuttosto semplici, informaticamente parlando. Si applicano a modelli matematicamente complessi ok, ma alla fine coinvolgono solo formulone che una volta determinate (a mano) basta inserirle nel sorgente del programma e poi ci pensa lui.
In casi del genere non mi è mai pesato troppo mettere mano a codice in versione 77 piuttosto che più moderno. Si, magari ci perdi un po' di tempo a capire perchè dà errore o perchè dà un risultato diverso da quello atteso, però niente di drammatico insomma.
Se tu è da due anni che usi il fortran conta che io sono almeno due anni che non scrivo un programma completo, quindi sono parecchio arrugginito (e dalle domande che faccio si vede! :) ).

Ho fatto un test, obiettivo: isolare l'eventuale flag di gfortran che dà problemi.
L'opzione "-O1" raggruppa diverse altre opzioni di ottimizzazioni. La "-O2" ne aggiunge alla precedente altre ancora. Invece "-O0" non ottimizza ed è il default come quando si compila senza opzioni di ottimizzazione.
Allora ho provato a compilare con "O1": se dà risultati buoni allora il flag problematico è tra quelli aggiunti da "O2", se invece ottengo il solito problema ecco che il flag problematico è uno di quelli aggiunti da "O1".

Il test ha prodotto un risultato balordo anche con "-O1".
Quindi il flag problematico è da ricercarsi tra quelli attivati con quell'opzione di compilazione.

Sono partito da qui.
https://gcc.gnu.org/onlinedocs/gfortran ... tions.html

Il problema è che in quella pagina non compare nè "-O2" ne "-O1"....
Forse sono opzioni meno specifiche... che riguardano la compilazione di codice anche diverso dal fortran tipo C etc..
Indagherò!
Al solito se sapete dare un consiglio, benvenga! :D

Avatar utente
joe
Iper Master
Iper Master
Messaggi: 3790
Iscritto il: ven 27 apr 2007, 11:21
Slackware: 15.0
Kernel: 5.15.38
Desktop: dwm

Re: Ottimizzare eseguibile affinchè giri più rapidamente

Messaggio da joe »

Partiamo dall'inizio.
Quale versione di gfortran sto usando (sono su slackware-14.0):

Codice: Seleziona tutto

$ gfortran -v
Reading specs from /usr/lib/gcc/i486-slackware-linux/4.7.1/specs
COLLECT_GCC=gfortran
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/i486-slackware-linux/4.7.1/lto-wrapper
Target: i486-slackware-linux
Configured with: ../gcc-4.7.1/configure --prefix=/usr --libdir=/usr/lib --mandir=/usr/man --infodir=/usr/info --enable-shared --enable-bootstrap --enable-languages=ada,c,c++,fortran,go,java,lto,objc --enable-threads=posix --enable-checking=release --enable-objc-gc --with-system-zlib --with-python-dir=/lib/python2.7/site-packages --disable-libunwind-exceptions --enable-__cxa_atexit --enable-libssp --enable-lto --with-gnu-ld --verbose --enable-java-home --with-java-home=/usr/lib/jvm/jre --with-jvm-root-dir=/usr/lib/jvm --with-jvm-jar-dir=/usr/lib/jvm/jvm-exports --with-arch-directory=i386 --with-antlr-jar=/root/slackware-current/source/d/gcc/antlr-runtime-3.4.jar --enable-java-awt=gtk --disable-gtktest --with-arch=i486 --target=i486-slackware-linux --build=i486-slackware-linux --host=i486-slackware-linux
Thread model: posix
gcc version 4.7.1 (GCC) 
A questo punto vado a vedere la documentazione della versione di gfortran in uso, cercando info su quali opzioni vengono attivate con il flag "-O1" (che genera un eseguibile bacato):
https://gcc.gnu.org/onlinedocs/gcc-4.7. ... ze-Options

Noto le righe iniziali del documento. Alcuni avvertimenti mi insospettiscono. Ma proseguo a fare un test:
compilo sostituendo al flag -O1 tutti i flags che lo stesso va ad attivare:

Codice: Seleziona tutto

          -fauto-inc-dec 
          -fcompare-elim 
          -fcprop-registers 
          -fdce 
          -fdefer-pop 
          -fdelayed-branch 
          -fdse 
          -fguess-branch-probability 
          -fif-conversion2 
          -fif-conversion 
          -fipa-pure-const 
          -fipa-profile 
          -fipa-reference 
          -fmerge-constants
          -fsplit-wide-types 
          -ftree-bit-ccp 
          -ftree-builtin-call-dce 
          -ftree-ccp 
          -ftree-ch 
          -ftree-copyrename 
          -ftree-dce 
          -ftree-dominator-opts 
          -ftree-dse 
          -ftree-forwprop 
          -ftree-fre 
          -ftree-phiprop 
          -ftree-sra 
          -ftree-pta 
          -ftree-ter 
          -funit-at-a-time
Risultato, l'eseguibile prodotto funziona bene come risultati stampati, ma è lento come senza opzioni di ottimizzazione.
Invece ripeto, mettendo il flag "-O1" (che dal documento avevo interpretato equivalente alla somma dei flag sopra riportati) l'eseguibile è molto più veloce, ma i risultati stampati sono errati.

In conclusione.. È evidente che "-O1" attiva anche altre opzioni oltre quelle sopra.
Ma quali?

Avatar utente
joe
Iper Master
Iper Master
Messaggi: 3790
Iscritto il: ven 27 apr 2007, 11:21
Slackware: 15.0
Kernel: 5.15.38
Desktop: dwm

Re: Ottimizzare eseguibile affinchè giri più rapidamente

Messaggio da joe »

Ho attivato anche altre opzioni che dal manuale vedo attivate con -O1 (perchè non specificarle tutte in modo preciso nel manuale? va bè)
Alla fine ecco come lancio la compilazione:

Codice: Seleziona tutto

gfortran  -fauto-inc-dec -fcompare-elim -fcprop-registers -fdce -fdefer-pop -fdse -fguess-branch-probability -fif-conversion2 -fif-conversion -fipa-pure-const -fipa-profile -fipa-reference -fmerge-constants -fsplit-wide-types -ftree-bit-ccp -ftree-builtin-call-dce -ftree-ccp -ftree-ch -ftree-copyrename -ftree-dce -ftree-dominator-opts -ftree-dse -ftree-forwprop -ftree-fre -ftree-phiprop -ftree-sra -ftree-pta -ftree-ter -funit-at-a-time -fdelayed-branch -fomit-frame-pointer -finline-functions-called-once -fdelete-null-pointer-checks -fcombine-stack-adjustments -fmove-loop-invariants -fauto-inc-dec -fdce -fdse -fshrink-wrap -ftree-reassoc -ftree-forwprop -ftree-fre -ftree-phiprop -ftree-copy-prop -fipa-pure-const -fipa-reference -fipa-pta -fipa-profile -ftree-sink -ftree-bit-ccp -ftree-ccp -ftree-dce -ftree-dominator-opts -ftree-dse -ftree-ch -ftree-loop-optimize -ftree-pta -ftree-sra -ftree-copyrename -ftree-ter --param loop-invariant-max-bbs-in-loop=1000 -o eseguibile.bin sorgente.f
f951: warning: this target machine does not have delayed branches [enabled by default]
Ok, salta fuori un warning che con -O1 non appare.
Ad ogni modo sembra che questo sia irrilevante ai fini dell'esecuzione del programma.

Esito:
Come prima, l'eseguibile gira, dà risultati corretti ma è lento.
Ancora una volta c'è qualcosa in più che il flag -O1 fà e che i singoli flags tutti insieme specificati come sopra riprortato.... bè, non fanno..
C'è qualche differenza quindi tra i flags fin qui aggiunti alla stringa di compilazione e il solo "-O1".

Se avete qualche vaga idea di dove andare a cercare queste ottimizzazioni in più.....
Non so magari sono altre opzioni che mi sono sfuggite nel manuale e che non ho aggiunto.

Avatar utente
lablinux
Linux 4.x
Linux 4.x
Messaggi: 1212
Iscritto il: gio 27 nov 2008, 12:23
Desktop: Gnome
Distribuzione: Debian testing
Località: Rho

Re: Ottimizzare eseguibile affinchè giri più rapidamente

Messaggio da lablinux »

fortran? E' un linguaggio che non conosco.

La domanda sorge spontanea, sei sicuro che con gfortran si possano avere le ottimizzazioni? Potrebbe essere il compilatore a "fregarsene" (termine non troppo tecnico).
Ci sono altri compilatori?

Puoi pubblicare il codice?

Avatar utente
joe
Iper Master
Iper Master
Messaggi: 3790
Iscritto il: ven 27 apr 2007, 11:21
Slackware: 15.0
Kernel: 5.15.38
Desktop: dwm

Re: Ottimizzare eseguibile affinchè giri più rapidamente

Messaggio da joe »

Non sono sicuro delle possibilità di gfortran ma penso proprio che accetti le opzioni di ottimizzazione. Volevo cercare di ottimizzare senza dover ricorrere ad altri compilatori. Come ho detto con "ifort" (quello della intel, ora a pagamento) alcuni mi dicevano che il programma gira molto più rapidamente rispetto a quello compilato con gfortran. E allora sono arrivato a leggere circa le opzioni di compilazione.

Se siano disponibili altri compilatori migliori non so, sicuramente ifort sarebbe una scelta papabile, ma preferirei stare sul Free, o al limite sul gratuito insomma.



Ne parlavano anche qui. Pertanto sembra che in teoria sia possibile ottimizzare anche con gfortran, tuttavia il mio risultato come quello della discussione linkata non è accettabile.
http://stackoverflow.com/questions/2168 ... aking-code

Alla fine sono giunto anche alla pagine seguente:
https://okpanico.wordpress.com/2012/07/ ... il-codice/

Non ho capito bene come funziona il tutto però ho provato a far girare il binario funzionante (quello lento per capirci):

Codice: Seleziona tutto

valgrind --tool=callgrind ./eseguibile.bin
Ho visionato cosa esce senza capirci granchè e poi ho fatto girare quello rapido ottimizzato con "-O1".

Codice: Seleziona tutto

valgrind --tool=callgrind ./eseguibile-O1.bin
Bè ho sotto il naso l'output ...
Gira molto lento con valgrind, però il numero riportato a schermo, quello che dovrebbe calare... bè stranamente effettivamente cala di iterazione in iterazione.
Eppure quando il programma gira "stand-alone" ecco che quel numero resta costante...
Qua c'è qualche inconveniente perchè la matematica non è un opinione. :)

In pratica rilevo che:
- se il binario targato -O1 viene fatto girare lentamente con la supervisione di valgrind, funziona.
- se lo stesso binario viene fatto girare come dovrebbe, cioè senza altri tool, le iterazioni progrediscono rapidissimamente, ma i risultati stampati per ciascuna non migliorano.

Ci capisco sempre meno...

PS
Il sorgente posso anche passarlo se volete provare a compilarlo ed eseguirlo. Ma non pubblicamente, no è roba mia, eventualmente ditemi in PM.

Rispondi