Il seguente programma chiamerà fun 2^(MAXD + 1) volte. La massima profondità di ricorsione non dovrebbe mai andare oltre il MAXD, anche se (se il mio pensiero è corretto). Quindi potrebbe volerci del tempo per compilare, ma non dovrebbe mangiare la mia RAM.Perché questo codice constexpr causa che GCC mangi tutta la mia RAM?
#include<iostream>
const int MAXD = 20;
constexpr int fun(int x, int depth=0){
return depth == MAXD ? x : fun(fun(x + 1, depth + 1) + 1, depth + 1);
}
int main(){
constexpr int i = fun(1);
std::cout << i << std::endl;
}
Il problema è che mangiare la mia RAM è esattamente quello che fa. Quando gira MAXD fino a 30, il mio laptop inizia a cambiare dopo che GCC 4.7.2 assegna rapidamente 3 GB circa. Non ho ancora provato con clang 3.1, in quanto non ho accesso ad esso in questo momento.
La mia unica ipotesi è che questo abbia qualcosa a che fare con GCC che cerca di essere troppo intelligente e memoize le chiamate alle funzioni, come con i modelli. Se è così, non sembra strano che non abbiano un limite alla quantità di memoizzazione che fanno, come le dimensioni di una tabella di cache MRU o qualcosa del genere? Non ho trovato un interruttore per disabilitarlo.
Perché dovrei farlo? Mi piace l'idea di creare una libreria di tempo di compilazione avanzata, come la programmazione genetica o qualcosa del genere. Dal momento che i compilatori non hanno l'ottimizzazione della coda di coda compilata, sono preoccupato che qualsiasi cosa abbia bisogno di ricorsione e (anche se alzo il massimo parametro di profondità di ricorsione, che sembra leggermente brutto da richiedere) allocherò rapidamente tutta la mia RAM e riempirò con cornici stack inutili. Così mi è venuta in mente la soluzione di cui sopra per ottenere arbitrariamente molte chiamate di funzione senza uno stack profondo. Tale funzione potrebbe essere utilizzata per piegare/avvolgere o trampollare.
EDIT: Ora l'ho provato in clang 3.1, e non perderà memoria, non importa per quanto tempo lo faccio funzionare (cioè quanto alto faccio MAXD). L'utilizzo della CPU è quasi del 100% e l'utilizzo della memoria è quasi dello 0%, proprio come previsto. Forse questo è solo un bug in GCC allora.
mi hanno confermato che lo stack non va mai oltre MAXD (come previsto), eseguendo la funzione runtime e osservando che mentre posso farlo funzionare per un lungo periodo, non usa affatto RAM. – Gurgeh
Potrebbe essere necessario segnalarlo come raccomandato in http://gcc.gnu.org/bugs/? – osgx
@osgx In realtà non è un bug, vero? Secondo lo standard, suppongo che possano fare ciò che vogliono nella mia RAM. Inoltre, vorrei qualcuno che sappia cosa stanno facendo (tu sai chi sei), dicendomi quale sia la ragione. – Gurgeh