Newsgroup: it.comp.lang.c
Titolo: FORTRAN è mio nemico

Salve NG,
 
scusate il subject, la domanda in realtà è seria.
 
Piccola premessa, per farvi scendere nello scenario..
Visto che, come al solito, mi scelgo compiti ingrati, mi trovo a fare il
porting di vecchio (vecchissimo) codice fortran (tradotto a sua volta
malissimo in C, in pratica "1-a-1", da un signore che ha evidentemente ritenuto
le sue incredibili competenze in fisica teorica sufficenti a rimpiazzare la
lettura di un manuale sul C - ma lasciamo perdere).
Premetto anche che non ho la più pallida idea dei calcoli che il programma
dovrebbe fare, visto che ho più difficoltà nel trovare la documentazione
necessaria a capire l'implementazione che a leggerla direttamente: per ora ho
solo il suo output e lo uso come test per quello che scrivo io.
Fine della premessa.
 
In più di una funzione ho una "svaccata" di variabili dai tipici nomi
fortran: a1,a2,...,a11,a12,a13,...,a234,b1000,b1001,...,b1423,etc. che
contengono i dati più disparati. Dal codice si riesce a capire, però, che
alcune rappresentano elementi di una matrice, alcune rappresentano i
coefficenti di un'equazione, e così via.
 
Il compito principale che mi sono prefisso (oltre, vabbè, a rendere il tutto
thread-safe, ma questo è un altro discorso) è di rendere il codice più
leggibile ma *non* più lento (anzi, se riuscissi a migliorarne le
prestazioni, tanto meglio, ma non è un requisito stringente: specifico la
cosa perché naturalmente utilizzare strumenti di alto livello rende il
lavoro più semplice, ma sono convinto che si possa fare bene anche senza, con
un po' di ragionamento).
 
Il primo pensiero è ovviamente sostiture le variabili che rappresentano
elementi di vettori o matrici con array. Questo rende ovviamente tutto più
leggibile ma, a livello di compilatore, quando le variabili son tante (aka le
matrici son "grossette"), per evitare troppe penalties dovrei pensare a come
fare riempire le cache in maniera furba, cosa che, a sua volta, rende il codice
più misterioso.
 
Il secondo pensiero naturalmente è quello di usare una libreria e/o far andare
i calcoli su SSEx (o perché no GPU, a 'sto punto). Ecco, per il codice in
oggetto sarebbe un po' un overkill e, IMO, non rende più leggibile il codice
se non per coloro che conoscono bene la libreria (o il funzionamento degli
specifici processori).
 
Il terzo pensiero è stato quello di fare un po' di prove e misurare, ma poi
(quarto pensiero) mi sono detto: sarà che forse su i.c.l.c qualcuno ha già
affrontato il problema? Un po' di esperienze simili mi salverebbero giornate
intere di lavoro!
 
Grazie mille dei consigli!
Ciao!
 
P.S.
Inutile dire che il progetto è open, non ci prendo una lira, e verrà rilasciato
al pubblico appena riesco a fare match (entro un margine d'errore decente)
con l'output degli applicativi ad oggi esistenti.
P.P.S.
Come ben sapete sono contrario a micro-ottimizzazioni e a ragionamenti del
tipo ma-forse-il-compilatore-farà. Ho posto la domanda perché, IMO, c'è
sempre, a parità di algoritmo e di performances, un modo più leggibile di
scrivere un codice, ed è quello che sto cercando di fare.


Il mio consiglio è non preoccuparti delle ottimizzazioni
 
Prima cerca di fare la conversione e preoccupati che funzioni, poi puoi 
anche iniziare a pensare alle ottimizzazioni
 

 scrivere un codice, ed è quello che sto cercando di fare.
 
Quindi alla fine vai con Python?
;-)
 
 
-- 
Andrea
 

 codice più misterioso.
 
Poiché leggo il NG da tempo so che ne sai più di me... ma
quoterei A.D'A sul compilatore. A quanto mi fu detto nella
mia pressoché unica esperienza di lavoro che avesse a che
fare con il dover ottimizzare un codice, il compilatore
ormai produce codice migliore di quanto possa fare un
essere umano. Ovviamente se l'algoritmo è scamuffo nulla
quaestio, ma credo non sia quello su cui focalizzi la tua
attenzione in questo progetto.
 
Credo che la cosa migliore sia un profiler e sperare che
questo individui delle zone relativamente isolate in cui
potrai lavorare con cura senza impazzire sul resto. Ma so
che dico una cosa ovvia...
 
-- 
Lei è Valentina e si fa chiamare Vale.
Lei è Caterina e si fa chiamare Cate.
Lei è Penelope e non le piacciono i soprannomi.
 

 quoterei A.D'A sul compilatore.
 
Apprezzo il rigore nell'abbreviazione ma dato che siamo su 
it.comp.lang, chiamami pure "ADA".
 
-- 
Andrea
 

 [...]
 
 
Ciao  Manlio

 dovrebbe fare, visto che ho più difficoltà nel trovare la documentazione
 
allora fai un porting 1-a-1 alla cazzo e basta.
Se vuoi usare librerie (ATLAS, CUDA,...) per velocizzare l'algoritmo o
capisci prima cosa fa l'algoritmo, oppure farai casini e basta.
E lascia fare ai compilatori il loro lavoro, lo faranno sicuramente
meglio di te.
 
Ciao Jack
-- 
Yoda of Borg am I! Assimilated shall you be! Futile resistance is, hmm?


 
l'avevo scritto in prima battuta ma poi ho corretto; non
osavo, metti mai che ADA ti fosse antipatico come lo è a
me... ^_^ [lo so che è un linguaggio eccezionale ed è
ancora usato per l'avionica e missilistica, eccetera,
ma... non lo amo]


 
 
Magari! Purtroppo non è sempre vero; specialmente con operazioni su 
grosse matrici:
http://people.freebsd.org/~lstewart/articles/cpumemory.pdf
 
 
 
 
Ciao  Manlio

 
http://people.freebsd.org/~lstewart/articles/cpumemory.pdf
 
 
e' per questo che hano inventato della librerie per gestire le matrici
(ATLAS, LAPACK,...). Inutile reinventare la ruota ogni volta.
 
In ogni modo e' meno doloroso spararsi nelle palle che tentare di fare
il porting di qualcosa di cui non si capisce come funziona...


 più misterioso.
 
Molto spesso le matrici di grandi dimensioni sono anche "sparse", cioè 
con molti elementi uguali a zero. Ci sono degli algoritmi apposta che 
sfruttano questa proprietà per semplificare i calcoli.
 
Come già ti dissero, è probabile che ti convenga prendere una libreria 
di algebra lineare invece di mettersi lì a fare il reverse engineering 
del codice...
 


Sì, è quello che sto facendo ovviamente, solo che, prima di scrivere per poi
buttare via, cercavo di fare una cosa ragionata. Ho comunque quasi finito
di farlo "male", quindi in pratica ho seguito il consiglio ;)
 
Ciao!

 
 
:) no, resto con il C!
 
Ciao!

 
 
Non c'è quasi nulla di algebra lineare, ma sicuramente è un'opzione.
 
Ciao!

 
 
Vero. Non sono quanto dolore si provi nel primo caso, ma sono sicuro che
quello che sto provando adesso è comparabile ;)
 
Ciao!


 
Come ho scritto in un'altra risposta non c'è quasi nulla di algebra lineare,
userei la libreria solo per la gestione dei dati.
 
Ciao!


Posso chiederti quale tool hai usato per la conversione ammesso che ne 
abbia usato uno ?
 
 
 

 abbia usato uno ?
 
Il tool di riferimento è f2c, ma immagino che l'OP abbia fatto a mano.
 
 
Ciao  Manlio


Sì, sto facendo a mano.. Ho tutto il codice fortran, un po' di C (quello
scritto male) e proprio ieri ho trovato qualche equazione; sto facendo il
classico fritto misto, anche se i test fanno ben sperare (non ho finito di
scrivere tutto ma già i risultati si avvicinano a quelli attesi)!
 
Ciao!

Le poche (pochissime) volte che ho dovuto passare dal formula al C, la
mia esperienza e` che iniziare cambiando i nomi delle variabili in
qualcosa che ha senso per quello che contengono, aiuta moltissimo a
capire tutto il resto dopo.
 
Per le ottimizzazioni, non mi impegnerei nemmeno 5 minuti, oggi come
oggi i compilatori sono abbastanza furbi da capire quando lo scope di
una variabile finisce e quindi "riciclarlo" per un altra. Anzi lo
scrivere in modo "semplice" sembra aiuti l'ottimizzatore molto piu'
che tentare di scrivere gia' 'ottimizzato'. Scusate il gioco di
parole.
-- 
andrea - ri mi cci, name


Da vedere però se i test sono affidabili/completi.
Se compili il codice fortran con il supporto per il test coverage, che 
copertura ottieni?
 
 
Ciao  Manlio

 
 
In generale sono d'accordo, nello specifico però ho visto più volte che
quando passi a multithread (a meno di non usare estensioni di compilatore,
tipo OpenMP, e ti affidi a, non so, le pthread) o vuoi diminuire i cache-miss,
al compilatore devi dare una mano, perché da solo non riesce bene (*)
 
Ciao!
 
(*) Ho sempre pensato che probabilmente succede perché apparentemente a
livello di applicativo si perdono delle prestazioni, che però si riacquistano
pensando a livello di sistema: le ultime volte che ho fatto queste prove
però era qualche annetto fa, magari oggi non succede più.. Il prossimo
progetto (o perché no questo, se faccio in tempo) farò qualche altra prova
così mi tengo aggiornato.
Di sicuro ci sono cose che vanno programmate esplicitamente perché il
compilatore non le può sapere, e quelle andranno sempre fatte a mano. Per
fare il solito esempio banale che è capitato a tutti, il dimensionamento di
vettori in base al PAGE_CLICK quando si scrive una struttura dati grossa e/o
sparsa o con backup su disco: è un'ottimizzazione, ma avendo bisogno di un
parametro ottenuto a real-time non può essere fatta dal compilatore!.

 
 
Mah, da quel punto di vista non son messo male: i test allegati all'originale,
manco a dirlo, sono veramente risicati; ho però in compenso un sacco di
input "reali" che posso fornire in parallelo ai due applicativi per poi
confrontare gli output (sempre che l'originale non si sbagli, ma a quel
punto oh, e che diamine! :D )
 
Ciao!

compilatore non le può sapere...
 
Ciao,
scusa se scrivo dopo tanto tempo.
 
Si e` vero, sono i cosidetti "hints" che dai al compilatore, ogni
compilatore ha la sua sintassi a proposito (quando ce l'ha...).
Faccio un esempio banale, usualmente le "if" sono gestite
nell'ottimizzatore come "not taken", e quando succede il "taken" molto
probabilmente nel processore la pipeline viene svuotata e il
processore ricomincia daccapo dall'istruzione dopo la if.
Solo il programmatore sa se nella logica di quello che scrive, la
condizione della 'if' e` piu` probabile che sia vera o falsa, e se e`
il caso, mette l'hint di "taken".
 
Un altro esempio e` quando forzi il compilatore a mettere come
'register' certe variabili, appunto perche' sai che dovra` essere
cosi`, per forza, in quel caso e in quel contesto di
macchina/compilatore/algoritmo.


 [...]
 
 
Ciao  Manlio


 
 
Anche qui i compilatori moderni sanno in genere ottimizzare meglio di un 
programmatore
 
Meglio lasciar fare al compilatore
 
 
 

 
 
void list_insert(list *head, void *elem)
{
    if (head==NULL) {
    } else {
    }
}
 
lo sappiamo tutti tranne il compilatore, cosa suggerire al branch predictor.
 
Ciao!


Vero, ma questo è un caso abbastanza speciale.
Io avevo in mente altri casi, in cui la probabilità dipende dal tipo di 
input (proveniente dall'esterno).
 
 
Ciao  Manlio

 input (proveniente dall'esterno).
 
Ma infatti questo tipo di hint non si usa praticamente mai. Personalmente l'ho
usato solo due o tre sul codice del mio OS, e anche sul codice del
kernel linux le macro "likely" e "unlikely" verranno usate una manciata di
volte al massimo (tramite una builtin del gcc poi, che non so se rispetti in
tutti i casi).
 
Ciao!