Tikz external & TeX capacity exceeded

  • Creatore
    Topic
  • #107764
    Up
    0
    Down
    ::


    Buongiorno,
    ieri sera mi è successa una cosa “strana” che mi ha fatto pensare di non aver ben capito cosa succede usando la libreria external di tikz….
    Sto scrivendo una relazione con una cinquantina di grafici in pgfplot di cui il 90% generati leggendo dati salvati su file .txt
    Visto che i tempi di compilazione erano diventati insostenibili già da qualche giorno avevo iniziato ad usare tikz external con grande soddisfazione.
    Ieri sera ho aggiunto alla fine del file una serie di listati che ho usato per produrre i grafici esposti in tutta la relazione.
    I listati li ho inclusi usando il comando \lstinputlisting definito da listings
    Tutto compilava alla perfezione e la mia relazione sembrava finita.
    Per la compilazione finale ho deciso di cancellare tutti i file temporanei salvati da tikz external e far rigenerare tutto da zero.
    In questa fase la compilazione si è interrota durante la generazione di un grafico. Leggendo il file .log generato da tikz external trovo il fatidico errore tex capacity exceeded
    La cosa che non capisco è che in questo file .log ci sono tutta una serie di warning che non hanno nulla a che vedere con la figura in questione. Ad esempio mi dice che ci sono delle label non definite, il che sarebbe normale (avendo cancellato i file ausiliari) se il log fosse stato del main file non di una figura generata da tikz external. La stessa compilazione in shell escape con il fatal error si arresta mentre sta leggendo un listato che io ho accluso alla fine del documento, a pagina 50. Il grafico che doveva generare è a pagina 3 😕 😕
    Adesso io pensavo che durante lo shell escape che tikz external compie venisse generato solo il grafico in questione, un pò come se stessi usando la classe standalone…ma leggendo il log direi che le cose non stanno così.

    La mia domanda quindi è: che cosa succede durante lo shell escape di tikz external?
    Viene compilata l’immagine in questione insieme a tutto il documento?
    Perché mi pare veramente strano….durante la compilazione del mio file allora il documento è stato composto 50 volte (una per grafico)? Mi sembra un comportamento così illogico…

    PS. Il documento alla fine l’ho compilato togliendo i codici, facendo generare tutti i grafici e poi rimettendo i codici.
    Non apro la discussione perché non riesco a compilare il file; la apro per capire che succede durante la compilazione con tikz external perché, evidentemente, non c’ho capito poi molto 🙂

Visualizzazione 4 filoni di risposte
  • Autore
    Risposte
    • #107765
      OldClaudio
      Partecipante
        Up
        0
        Down
        ::


        Qualcuno più esperto di me può spiegarti che cosa succede con tikzexternal.
        A me pare che la TeX capcity exceeded dipenda dal fatto che pdfplots è un divoratore di memoria, tanto che bisogna agire sulle impostazioni di pdftex per destinare molta più memoria (main memory).
        Se ne è parlato diverse volte qui sul forum; ora non ho tempo di cercarti i filoni di discussione dove se ne è parlato, ma non dovrebbe essere dificile e troppo lungo usare la funzione Cerca del forum specificando parole chiave ben scelte.

      • #107766
        Up
        0
        Down
        ::


        Si, il fatto che pgfplot divori la memoria, limitata, di latex mi è chiaro. Sono anche a conoscenza del fatto che questa possa essere aumentata e le istruzioni per farlo sono nella stessa documentazione di pgfplot. La mia domanda verteva più sul funzionamento di tikz external perché l’errore di tex capacity exceeded mi ha fatto sorgere diversi dubbi su quale sia il suo effettivo principio di funzionamento. Questi dubbi poi mi fanno anche pensare che forse c’è qualche modo più efficiente di quello che ho usato per sfruttare tutto il processo e per convivere con le limitazioni di memoria di latex. Ad esempio per i grafici più complessi potrebbe essere il caso di usare standalone in modo da avere tutta la memoria di tex impegnata a generare quel singolo grafico e invece usare il tikz external per i grafici più semplici.

        Ho poi letto che lualatex non ha questi problemi di memoria. Per questo documento sicuramente non passerò a lualatex visto che il documento l’ho compilato ma, magari, in futuro potrebbe essere una idea.

        Insomma per capire quale sia la strada migliore per operare in futuro su casi simili volevo capire il funzionamento effettivo di tikz external 😉

      • #107767
        Liverpool
        Partecipante
          Up
          0
          Down
          ::

          Little” post=107896Adesso io pensavo che durante lo shell escape che tikz external compie venisse generato solo il grafico in questione, un pò come se stessi usando la classe standalone…ma leggendo il log direi che le cose non stanno così.

          La mia domanda quindi è: che cosa succede durante lo shell escape di tikz external?
          Viene compilata l’immagine in questione insieme a tutto il documento?
          Perché mi pare veramente strano….durante la compilazione del mio file allora il documento è stato composto 50 volte (una per grafico)? Mi sembra un comportamento così illogico…

          Quando compili, la libreria di TikZ controlla se sono presenti i file .dpth relativi all’immagine che vuoi inserire. Se ci sono, usa il pdf relativo, altrimenti compila il grafico e lo allega. Non compila il documento tante volte quante sono le immagini. Il problema (da quello che era emerso su questo forum) è che pgfplots non svuota la memoria dopo ogni grafico, perciò anche se ci sono grafici semplicissimi, se sono tanti si può incorrere comunque nella limitazione di memoria, che è quello che è successo a te quando hai dovuto rigenerare tutti i grafici da zero.

          Domanda: se compili il documento disattivando la libreria external ti dà errore comunque? Se sì, il problema non è della libreria.

        • #107768
          Up
          0
          Down
          ::

          Quando compili, la libreria di TikZ controlla se sono presenti i file .dpth relativi all’immagine che vuoi inserire. Se ci sono, usa il pdf relativo, altrimenti compila il grafico e lo allega. Non compila il documento tante volte quante sono le immagini.

          Questo era quello che pensavo anche io…insieme al file .dpth però c’è anche il file .log che dovrebbe riguardare la compilazione della singola immagine. Non capisco però perché ci sono scritte cose che con l’immagine non hanno nulla a che vedere (come le label non definite)

          Il problema (da quello che era emerso su questo forum) è che pgfplots non svuota la memoria dopo ogni grafico, perciò anche se ci sono grafici semplicissimi, se sono tanti si può incorrere comunque nella limitazione di memoria, che è quello che è successo a te quando hai dovuto rigenerare tutti i grafici da zero.

          Io ho un grafico particolarmente rognoso perché è un grafico 3d in cui c’è disegnata più di una curva. Questa immagine singolarmente viene compilata ma nel documento senza usare external la compilazione si arresta quando arriva a questa immagine. Evidentemente quindi la colpa di ciò è quella che indichi anche tu; ovvero che pgfplot non svuota la memoria dopo ogni grafico.

          Analizziamo però adesso quello che succede se io faccio una prova diversa.
          Prendo il documento per intero con tutti i grafici (che sono 54) ma a cui taglio i listati finali (sono 16 listati per 20 pagine totali)
          Lo compilo usando external (facendogli rigenerare tutti i grafici) e la compilazione funziona
          Lo compilo senza external e la compilazione si ferma al grafico 3d di cui sopra (che è il grafico n.4 in ordine di apparizione)

          Questo mi induce a pensare che le cose vadano così:
          C’è un processo principale che è quello di pdflatex dell’intero documento. Questo procede fino alla prima immagine
          A questo punto external lancia un secondo processo in shell-escape dove compila l’immagine e produce i vari file ausiliari
          Il processo lanciato da external finisce e, finendo, libera memoria.
          La palla torna al processo principale che prende il pdf generato, lo include e va avanti fino al \begin{tikzpicture} successivo
          […]

          Ciò mi farebbe pensare che, in realtà, usando external la gestione della memoria migliori e non di poco (senza external riesco a compilare 3 grafici, con external 54)

          Ma allora, stando così le cose, per quale motivo aggiungere dei listati in coda al documento dovrebbe avere qualche importanza nella compilazione di external?
          Aggiungendo i listati in coda infatti quello che succede è che il processo di shell escape che viene compiuto da external durante la compilazione del quarto grafico si blocca.
          Nel file chiamato Main-figure3.log troviamo infatti scritto
          `
          File: latin1.def 2015/03/17 v1.2c Input encoding file
          ) (./script/1.script.m
          ! TeX capacity exceeded, sorry [main memory size=5000000].

          \reset@color
          l.82 Mz1(
          k2)=(sum(bin2(k2)-mean(z))^1)*pz(k2);
          Here is how much of TeX's memory you used:
          44405 strings out of 493027
          1026914 string characters out of 6134070
          5000000 words of memory out of 5000000
          47269 multiletter control sequences out of 15000+600000
          124736 words of font info for 98 fonts, out of 8000000 for 9000
          1141 hyphenation exceptions out of 8191
          74i,21n,100p,10419b,3293s stack positions out of 5000i,500n,10000p,200000b,80000s

          ! ==> Fatal error occurred, no output PDF file produced!
          `
          La compilazione di questa immagine si arresta quindi quando il processo cerca di leggere il file {./script/script1.m} ed arriva alla riga 82.
          Questo file è uno di quelli che ho incluso alla fine del documento e la riga 82 è esattamente quella riportata nel log.

          Continuo a non capacitarmi del perché se deve generare una immagine che sta a pagina 5 lui arrivi a leggere una cosa che sta a pagina 45. Dovrebbe essere il processo principale di pdflatex che va ad analizzare questi file, non lo shell-escape chiamato da external….no? 😕

        • #107769
          Up
          0
          Down
          ::


          Sono andato in fondo alla questione e ho capito che stavo leggendo la documentazione sbagliata (tanto per cominciare). La documentazione di tikz è ben più approfondita di quella di pgfplot riguardo la libreria externalize. Pubblico quindi questo post perché magari può essere utile anche ad altri sapere come funzionano le cose

          Quello che succede è sostanzialmente questo:
          Durante la compilazione del file principale externalize entra in funzione quando trova \begin{tikzpicture} o \tikz. Se l’immagine finale non è disponibile ma deve essere generata la libreria si preoccupa di generarla (e fin qui nulla di nuovo).
          La generazione consiste in una compilazione completa del file main in cui tutto il documento viene compilato e ma alcuni comandi vengono saltati. L’unico ambiente tikzpicture ad essere compilato è quello dell’immagine da generare mentre gli altri vengono ignorati così come vengono ignorati i comandi includegraphics (e volendo si possono specificare altri comandi da escludere). Il resto del documento viene processato interamente ma il processo di output produce un pdf con solo l’immagine desiderata, buttando il resto.
          Una volta che l’immagine è stata generata la compilazione primaria prosegue fino all’immagine successiva.

          Questo comporta un paio di cose:
          1. Effettivamente se ci sono 10 immagini il documento verrà compilato 11 volte (la prima volta sarà quindi più lungo rispetto a non usare externalize ma il processo sarà indolore tutte le compilazioni successive)
          2. Questa libreria permette di migliorare l’uso della memoria di latex. Come ho scritto anche nel messaggio precedente compilando una immagine alla volta dopo ogni immagine la memoria si resetta; cosa che non succede non usando externalize.
          3. L’immagine non viene comunque compilata da sola ma questa deve essere abbastanza “leggera” da poter essere compilata insieme a tutto il resto del documento (altre immagini escluse, ovviamente). Per le immagini più pesanti la classe standalone non soffre di questo problema e può essere magari una alternativa

          Per come la vedo io un miglioramento sensibile della libreria sarebbe quello di compilare solo l’immagine da generare nei vari processi secondari. Probabilmente la libreria agisce in questo modo per essere sicuri che le immagini siano complete di tutto e che non ci sia una parte di codice che influisca sull’immagine e che non venga compilata.
          Se il problema fosse questo una possibile miglioria della libreria potrebbe essere quella di utilizzare il comando (che già esiste) \tikzsetnextfilename{⟨file name⟩} come delimitatore di ciò che viene compilato nei vari processi secondari (ovviamente poi è compito di chi usa la libreria quello di assicurarsi che tutto il codice sia nel posto giusto)
          Quindi se un codice è fatto tipo
          `\tikzsetnextfilename{figura1}
          \begin{tikzpicture}
          […]
          \end{tikzpicture}
          \tikzsetnextfilename{figura2}
          [testo….]
          \begin{tikzpicture}
          […]
          \end{tikzpicture}`
          si potrebbe fare in modo che nella prima compilazione ausiliaria venga compilata solo la porzione di documento tra i primi due \tikzsetnextfilename (con lo stesso preambolo del mainfile), mentre la seconda volta dal secondo \tikzsetnextfilename fino a \end{document}.
          Se non ci sono comandi \tikzsetnextfilename la compilazione avviene come ora.
          Adesso io non so se questa strada sia tecnicamente percorribile e non penso di avere le competenze per provare a percorrerla. La scrivo lo stesso, magari è di ispirazione per qualcuno 🙂

      Visualizzazione 4 filoni di risposte
      • Devi essere connesso per rispondere a questo topic.

      Go to top