Rapidità di esecuzione dello scalamento di una lunghezza

  • Creatore
    Topic
  • #80677
    Liverpool
    Partecipante
      Up
      0
      Down
      ::


      Devo moltiplicare una lunghezza per un numero razionale. E’ più veloce il riassegnamento del nuovo valore (es: [tt]\len=0.5\len[/tt]) oppure il passaggio attraverso [tt]\multiply[/tt] e [tt]\divide[/tt]? A parte questo, i due metodi risultano indifferenti?

      Grazie

    Visualizzazione 13 filoni di risposte
    • Autore
      Risposte
      • #80678
        Up
        0
        Down
        ::

        Liverpool” post=79856Devo moltiplicare una lunghezza per un numero razionale. E’ più veloce il riassegnamento del nuovo valore (es: [tt]\len=0.5\len[/tt]) oppure il passaggio attraverso [tt]\multiply[/tt] e [tt]\divide[/tt]? A parte questo, i due metodi risultano indifferenti?

        Se eseguo dieci milioni di volte l’assegnazione
        `\dimen2=1.5\dimen0`
        (avendo già detto [tt]\dimen0=1cm[/tt]) impiego un tempo di circa 20 secondi.

        Lo stesso test sull’assegnazione
        `\dimen2=\dimen0 \multiply \dimen2 by 3 \divide\dimen2 by 2`
        ne richiede circa 30.

        Il test è (in Plain TeX)
        `\dimen0=1cm
        %\def\a{\dimen2=1.5\dimen0 }
        \def\a{\dimen2=\dimen0 \multiply \dimen2 by 3 \divide\dimen2 by 2 }
        \def\b{\a\a\a\a\a\a\a\a\a\a}
        \def\c{\b\b\b\b\b\b\b\b\b\b}
        \def\d{\c\c\c\c\c\c\c\c\c\c}
        \def\e{\d\d\d\d\d\d\d\d\d\d}
        \def\f{\e\e\e\e\e\e\e\e\e\e}
        \def\g{\f\f\f\f\f\f\f\f\f\f}
        \def\h{\g\g\g\g\g\g\g\g\g\g}

        \h
        \bye`
        e si può trascurare il tempo necessario per le espansioni.

        In conclusione non vedo perché farsi problemi: dieci milioni di quelle assegnazioni sono una quantità alquanto esagerata per un normale documento anche di grandi dimensioni.

        Ciao
        Enrico

      • #80679
        Liverpool
        Partecipante
          Up
          0
          Down
          ::

          egreg9″ post=79858In conclusione non vedo perché farsi problemi: dieci milioni di quelle assegnazioni sono una quantità alquanto esagerata per un normale documento anche di grandi dimensioni.

          Grazie. Era una curiosità di tipo teorico, non una vera esigenza. Mi piace non trascurare niente.

        • #80680
          Liverpool
          Partecipante
            Up
            0
            Down
            ::

            egreg9″ post=79858In conclusione non vedo perché farsi problemi: dieci milioni di quelle assegnazioni sono una quantità alquanto esagerata per un normale documento anche di grandi dimensioni.

            Grazie. Era una curiosità di tipo teorico, non una vera esigenza. Mi piace non trascurare niente.

          • #80681
            Liverpool
            Partecipante
              Up
              0
              Down
              ::


              Ho un’altra domanda (stupida) sugli operatori, perciò la scrivo qui.
              [tt]\dimen0=0.25\dimen0[/tt] è la stessa cosa di [tt]\divide\dimen0 by 4[/tt]?
              Dove posso trovare un riferimento completo sulle operazioni, per non dare più fastidio sul forum?

              Grazie

            • #80682
              Up
              0
              Down
              ::

              Liverpool” post=80129Ho un’altra domanda (stupida) sugli operatori, perciò la scrivo qui.
              [tt]\dimen0=0.25\dimen0[/tt] è la stessa cosa di [tt]\divide\dimen0 by 4[/tt]?
              Dove posso trovare un riferimento completo sulle operazioni, per non dare più fastidio sul forum?

              Grazie

              Sessione interattiva con TeX:
              `This is TeX, Version 3.1415926 (TeX Live 2012)
              **\relax

              *\dimen0=3cm

              *\dimen0=0.25\dimen0

              *\message{\number\dimen0}
              1398509
              *\dimen0=3cm

              *\divide\dimen0 by 4

              *\message{\number\dimen0}
              1398509`
              Sì, è lo stesso, perché puoi esprimere 1/4 con un decimale finito con meno di cinque cifre decimali. Proseguiamo:
              `*\dimen0=3cm

              *\divide\dimen0 by 3

              *\message{\number\dimen0}
              1864679
              *\dimen0=3cm

              *\dimen0=.33333\dimen0

              *\message{\number\dimen0}
              1864651`
              Come vedi c’è una differenza di 28sp, per via dell’aritmetica intera (binaria) usata internamente.

              Devi preoccuparti? No. Tanto non otterrai praticamente mai il “vero” valore: se proseguiamo da dov’eravamo, abbiamo questo:
              `*\setbox0=\hbox to 3cm{\hskip\dimen0 \hskip\dimen0 \hskip\dimen0 }

              Underfull \hbox (badness 10000) detected at line 0

              *\dimen0=3cm

              *\divide\dimen0 by 3cm

              *\setbox0=\hbox to 3cm{\hskip\dimen0 \hskip\dimen0 \hskip\dimen0 }

              Underfull \hbox (badness 10000) detected at line 0`
              Che ci si può fare? Niente, se non aggiungere qualche [tt]\hfil[/tt]

              Ciao
              Enrico

            • #80683
              Liverpool
              Partecipante
                Up
                0
                Down
                ::


                Lo so che non si scrive un messaggio solo per ringraziare, ma ti ringrazio tanto per la pazienza. Mi rendo conto che per te sono cose scontate e per questo apprezzo ancora di più il tempo che hai impiegato per rispondermi. Ma se dovessi consigliarmi un riferimento, cosa mi consiglieresti? E per LaTeX3 c’è qualcosa per principianti?

                Grazie

              • #80684
                OldClaudio
                Partecipante
                  Up
                  0
                  Down
                  ::


                  Sia sulla Guida Guit sia nella guida tematica LaTeX Reference Manual commentato ho cercato di descrivere questa aritmetica 2fixed radix” come la chiama Knuth. Non credo che i miei esempi siano migliori degli esempi che ti ha fatto Enrico e non c’è molto di più da capire.

                  Lua(La)Tex consente attraverso Lua di eseguire dell’aritmetica floating point. Ma tranne in casi particolari direi che l’aritmetica intera fixed radix è sufficiente nella maggior parte dei casi.

                  La tua domanda in realtà, se ho capito bene, riguarda la velocità delle operazioni ottenute con \divide oppure con il coefficiente fratto già calcolato. Secondo quello che ho capito io la moltiplicazione per il coefficiente fratto è più onerosa rispetto alla divisione per un intero. Ma stiamo parlando di microsecondi, quindi in realtà si tratta di tempi del tutto trascurabili per i quali non vale la pena di preoccuparsi.

                • #80685
                  Liverpool
                  Partecipante
                    Up
                    0
                    Down
                    ::

                    OldClaudio” post=80163La tua domanda in realtà, se ho capito bene, riguarda la velocità delle operazioni ottenute con \divide oppure con il coefficiente fratto già calcolato

                    Ti ringrazio per la risposta. Ho letto la preziosissima guida Guit, ma pensavo ci fosse qualcosa di più da sapere.
                    La mia prima domanda riguardava effettivamente il confronto per l’impiego di risorse tra moltiplicazione + divisione oppure moltiplicazione per numero razionale + riassegnamento.
                    La seconda domanda, invece, riguardava il risultato dell’operazione (e su questo ci sono degli esempi sulla tua guida).

                    Ciao e bentornato

                  • #80686
                    OldClaudio
                    Partecipante
                      Up
                      0
                      Down
                      ::

                      Ciao e bentornato

                      Grazie epr il bentornato; certo sono tornato un poco sul forum e lo faccio quando riesco a trovere una free WiFi. In realtà sono a circa 17 000 km di distanza nello stato di Vittoria, in Australia:smile:

                      Tornado al tuo problema Lo scalamanto di una lunghezza andrebbe fatto nel modo migliore sia per precisione, sia per velocità ricorrendo alle estensioni di eTeX che da diversi anni sono incorporate dentro ogni motore di composizione moderno, pdftex, xetex,luatex e forse anche altri. Questi sono i nomi dei veri programmi di composizione che insieme al file di formato latex.ltx formano pdflatex, xelatex, lualatex.

                      Allora per scalare di un fattore 0.25 ovvero 1/4 hai queste possibilità:`\dimen0= \dimexpr \dimen0 * 0.25pt / 1pt \relax`oppure` \dimen0 = \dimexpr \dimen0 * 1pt / 4pt \relax`

                      I due \relax sono facoltativi se non ci sono ambiguità con quel che segue; le dimensioni in puti tipografic possono venire rappresentate come multipli di \p@.

                      Il bello della \dimexpr è che la prima moltiplicazione viene eseguita in un registro da 64 bit (invece della lunghezza normale di 32 bit), quidi senza troncamenti né overflow. La divisione viene eseguite con il numeratore intero a doppia precisione e arrotondato, non troncato come succede con \divide. Sono due operazioni eseguite direttamente nei registri della CPU, quindi richiedono il minimo tempo macchina possibile. Il manuale di eTeX raccomanda di eseguire le operazioni di scalamento in questo modo. texdoc etex è illuminante a questo proposito.

                      Ciao
                      Claudio

                    • #80687
                      Up
                      0
                      Down
                      ::

                      OldClaudio” post=80166

                      Ciao e bentornato

                      Grazie epr il bentornato; certo sono tornato un poco sul forum e lo faccio quando riesco a trovere una free WiFi. In realtà sono a circa 17 000 km di distanza nello stato di Vittoria, in Australia:smile:

                      Tornado al tuo problema Lo scalamanto di una lunghezza andrebbe fatto nel modo migliore sia per precisione, sia per velocità ricorrendo alle estensioni di eTeX che da diversi anni sono incorporate dentro ogni motore di composizione moderno, pdftex, xetex,luatex e forse anche altri. Questi sono i nomi dei veri programmi di composizione che insieme al file di formato latex.ltx formano pdflatex, xelatex, lualatex.

                      Allora per scalare di un fattore 0.25 ovvero 1/4 hai queste possibilità:`\dimen0= \dimexpr \dimen0 * 0.25pt / 1pt \relax`oppure` \dimen0 = \dimexpr \dimen0 * 1pt / 4pt \relax`

                      I due \relax sono facoltativi se non ci sono ambiguità con quel che segue; le dimensioni in puti tipografic possono venire rappresentate come multipli di \p@.

                      Il bello della \dimexpr è che la prima moltiplicazione viene eseguita in un registro da 64 bit (invece della lunghezza normale di 32 bit), quidi senza troncamenti né overflow. La divisione viene eseguite con il numeratore intero a doppia precisione e arrotondato, non troncato come succede con \divide. Sono due operazioni eseguite direttamente nei registri della CPU, quindi richiedono il minimo tempo macchina possibile. Il manuale di eTeX raccomanda di eseguire le operazioni di scalamento in questo modo. texdoc etex è illuminante a questo proposito.

                      Ciao
                      Claudio

                      Temo che non sia proprio vero. L’esecuzione di
                      `\dimen2=\dimexpr\dimen0*3/2\relax`
                      richiede essenzialmente lo stesso tempo di
                      `\dimen2=\dimen0 \multiply\dimen2 by 3 \divide\dimen2 by 2`

                      La sintassi che proponi
                      `\dimexpr \dimen0 * 0.25pt / 1pt \relax`
                      è scorretta. Se infatti provi questa sessione interattiva
                      `$ pdftex
                      This is pdfTeX, Version 3.1415926-2.4-1.40.13 (TeX Live 2012)
                      restricted \write18 enabled.
                      **\relax
                      entering extended mode

                      *\dimen0=1cm

                      *\dimen0=\dimexpr \dimen0 * 0.25pt / 1pt \relax

                      *\showthe\dimen0
                      > 0.0pt.
                      <*> \showthe\dimen0

                      ?

                      *\bye
                      [1{/usr/local/texlive/2012/texmf-var/fonts/map/pdftex/updmap/pdftex.map}]
                      Output written on texput.pdf (1 page, 11260 bytes).
                      Transcript written on texput.log.`
                      scopri che \dimexpr finisce con lo 0 e troverai “.25pt / 1pt” nel PDF finale.

                      Ciao
                      Enrico

                    • #80688
                      Liverpool
                      Partecipante
                        Up
                        0
                        Down
                        ::

                        egreg9″ post=80168Temo che non sia proprio vero. L’esecuzione di
                        `\dimen2=\dimexpr\dimen0*3/2\relax`
                        richiede essenzialmente lo stesso tempo di
                        `\dimen2=\dimen0 \multiply\dimen2 by 3 \divide\dimen2 by 2`

                        Però sul manuale di [tt]etex[/tt] c’è scritto

                        manuale di etexLe operazioni aritmetiche sono eseguite individualmente, tranne le operazioni di ‘scalamento’ (una moltiplicazione seguita immediatamente da una divisione) che sono eseguite come un’operazione combinata con un prodotto a 64 bit come valore intermedio

                        Questa frase sembra voler dire che mentre nella successione [tt]multiply+divide[/tt] le operazioni sono:
                        a) carico il numero
                        b) eseguo la moltiplicazione
                        c) scarico il numero
                        d) carico il numero
                        e) eseguo la divisione
                        f) scarico il numero

                        con le istruzioni di [tt]etex[/tt] le operazioni sono:
                        a) carico il numero
                        b) eseguo la moltiplicazione
                        c) eseguo la divisione sul numero in registro
                        d) scarico il numero

                        quindi si dovrebbe risparmiare un carico+scarico, se ho capito bene. Forse tu dici che alla fine si tratta di tempi infinitesimi?


                        @OldClaudio
                        , perché dici nel primo messaggio che la moltiplicazione per coefficiente fratto dovrebbe essere più onerosa della divisione per numero intero?

                        Ciao

                      • #80689
                        Up
                        0
                        Down
                        ::

                        Liverpool” post=80170

                        Temo che non sia proprio vero. L’esecuzione di
                        `\dimen2=\dimexpr\dimen0*3/2\relax`
                        richiede essenzialmente lo stesso tempo di
                        `\dimen2=\dimen0 \multiply\dimen2 by 3 \divide\dimen2 by 2`

                        Però sul manuale di [tt]etex[/tt] c’è scritto

                        manuale di etexLe operazioni aritmetiche sono eseguite individualmente, tranne le operazioni di ‘scalamento’ (una moltiplicazione seguita immediatamente da una divisione) che sono eseguite come un’operazione combinata con un prodotto a 64 bit come valore intermedio

                        Questa frase sembra voler dire che mentre nella successione [tt]multiply+divide[/tt] le operazioni sono:
                        a) carico il numero
                        b) eseguo la moltiplicazione
                        c) scarico il numero
                        d) carico il numero
                        e) eseguo la divisione
                        f) scarico il numero

                        con le istruzioni di [tt]etex[/tt] le operazioni sono:
                        a) carico il numero
                        b) eseguo la moltiplicazione
                        c) eseguo la divisione sul numero in registro
                        d) scarico il numero

                        quindi si dovrebbe risparmiare un carico+scarico, se ho capito bene. Forse tu dici che alla fine si tratta di tempi infinitesimi?

                        Quel poco che si guadagna da un’assegnazione in meno si perde con l’uso di [tt]\dimexpr[/tt] che è più lento della manipolazione diretta dei registri.

                        Ciao
                        Enrico

                      • #80690
                        OldClaudio
                        Partecipante
                          Up
                          0
                          Down
                          ::


                          Sì, lo so che quell’espressione è sbagliata; volevo solo rendere l’idea; in realtà non ci sono problemi a mettere numeratore e denominatore dello scalamento in due registri lunghezza e usare i registri invece dei valori espliciti.
                          IN vece non sono d’accordo sul fatto che eseguendo le operazioni direttamente sui registri si ottenga lo stesso risultato. Infatti il prodotto parziale deve essere a 32 bit se si usano le operazioni primitive di TeX, mentre con \dimexpr si ha un valore intermedio a 64 bit; per cui si riduce a metà il pericolo dell’overflow. Inoltre \dimexpr esegue direttamente l’arrotondamento invece del troncamanto, il che, se vogliamo è solo estetica.

                          Per quel che riguarda i tempi di esecuzione di \dimexpr non sono certo che siano maggiori di quelli dei comandi tradizionali, in quanto sono direttamente programmati nell’eseguibile come operazioni di long integer, almeno la moltiplicazione. Detto questo ribadisco che non sono certo perché non ho letto il volume TeX the program, dove per altro Knuth non ha descritto il codice di eTeX. Non ho nemmeno letto il codice sorgente delle “modifiche” di eTeX da inserire durante la compilazione dell’eseguibile (che per altro a noi utenti arriva già fatta con l’installazione prescelta — molti anni fa mettevo le mani sul codice Pascal e ricompilavo il tutto sul VAX su cui avevo accesso come amministratore, ma non mi sogno più di fare cose del genere.

                          Per lo stesso motivo, @Liverpool; non sono in grado di spiegarti come nel TeX tradizionale di Knuth i registri interi che contengono il numero di scaled points vengano gestiti per moltiplicare il loro contenuto per quantità fratte; non son un mago della programmazione assembler, anzi, ma ho lavorato in questo campo in passato e non conosco altre vie di spezzare le operazioni fra parte intera e parte fratta del fattore fratto (be’, io a suo tempo sarei passato per una conversino in reale, anche se facendo ciò avrei avuto una perdita di bit significativi con lunghezze grandicelle; con gli scaled points interi arrivi a 2^{30}-1, mentre con i floaitng point arrivi fino a 2^(25)-1 bit significativi contando anche il primo bit nascosto che è sempre un 1). Se hai mai programmato a bassissimo livello, praticamente assembler o linguaggio macchina, sai di che cosa sto parlando. Ma anche senza questa esperienza capisci da solo che scalare per una quantità fratta un numero intero richiede accrcochi strani se si vuole rimanere nel dominio dei numeri interi.

                          Se qualcuno più volonterosi di quanto io non sia, volesse leggersi il secondo libro della Millennium Edition di Knuth, il testo che descrive il programma sorgente di TeX, e ci spiega in dettaglio come vengano eseguiti questi scalamenti restando nel dominio degli interi è il benvenuto, almeno da parte mia.

                        • #80691
                          Up
                          0
                          Down
                          ::

                          OldClaudio” post=80172Per quel che riguarda i tempi di esecuzione di \dimexpr non sono certo che siano maggiori di quelli dei comandi tradizionali, in quanto sono direttamente programmati nell’eseguibile come operazioni di long integer, almeno la moltiplicazione.

                          Prova. 🙂

                          1. Contenuto di [tt]testdim.tex[/tt]
                          `\dimen0=1cm
                          \def\a{\dimen2=1.5\dimen0 }
                          %\def\a{\dimen2=\dimen0 \multiply \dimen2 by 3 \divide\dimen2 by 2 }
                          %\def\a{\dimen2=\dimexpr\dimen0 * 3/2\relax}
                          \def\b{\a\a\a\a\a\a\a\a\a\a}
                          \def\c{\b\b\b\b\b\b\b\b\b\b}
                          \def\d{\c\c\c\c\c\c\c\c\c\c}
                          \def\e{\d\d\d\d\d\d\d\d\d\d}
                          \def\f{\e\e\e\e\e\e\e\e\e\e}
                          \def\g{\f\f\f\f\f\f\f\f\f\f}
                          \def\h{\g\g\g\g\g\g\g\g\g\g}

                          \h
                          \bye`

                          Risultato:
                          `$ \time testdim.tex
                          testdim.tex: No such file or directory
                          0.00 real 0.00 user 0.00 sys
                          [eg-macmini:~/provaccia] enricomb% \time pdftex testdim.tex
                          This is pdfTeX, Version 3.1415926-2.4-1.40.13 (TeX Live 2012)
                          restricted \write18 enabled.
                          entering extended mode
                          (./testdim.tex )
                          No pages of output.
                          Transcript written on testdim.log.
                          11.59 real 10.66 user 0.09 sys`

                          2. Contenuto di [tt]testdim.tex[/tt]
                          `\dimen0=1cm
                          %\def\a{\dimen2=1.5\dimen0 }
                          \def\a{\dimen2=\dimen0 \multiply \dimen2 by 3 \divide\dimen2 by 2 }
                          %\def\a{\dimen2=\dimexpr\dimen0 * 3/2\relax}
                          \def\b{\a\a\a\a\a\a\a\a\a\a}
                          \def\c{\b\b\b\b\b\b\b\b\b\b}
                          \def\d{\c\c\c\c\c\c\c\c\c\c}
                          \def\e{\d\d\d\d\d\d\d\d\d\d}
                          \def\f{\e\e\e\e\e\e\e\e\e\e}
                          \def\g{\f\f\f\f\f\f\f\f\f\f}
                          \def\h{\g\g\g\g\g\g\g\g\g\g}

                          \h
                          \bye`

                          Risultato:
                          `$ \time pdftex testdim.tex
                          This is pdfTeX, Version 3.1415926-2.4-1.40.13 (TeX Live 2012)
                          restricted \write18 enabled.
                          entering extended mode
                          (./testdim.tex )
                          No pages of output.
                          Transcript written on testdim.log.
                          16.28 real 15.48 user 0.11 sys`

                          3. Contenuto di [tt]testdim.tex[/tt]
                          `\dimen0=1cm
                          %\def\a{\dimen2=1.5\dimen0 }
                          %\def\a{\dimen2=\dimen0 \multiply \dimen2 by 3 \divide\dimen2 by 2 }
                          \def\a{\dimen2=\dimexpr\dimen0 * 3/2\relax}
                          \def\b{\a\a\a\a\a\a\a\a\a\a}
                          \def\c{\b\b\b\b\b\b\b\b\b\b}
                          \def\d{\c\c\c\c\c\c\c\c\c\c}
                          \def\e{\d\d\d\d\d\d\d\d\d\d}
                          \def\f{\e\e\e\e\e\e\e\e\e\e}
                          \def\g{\f\f\f\f\f\f\f\f\f\f}
                          \def\h{\g\g\g\g\g\g\g\g\g\g}

                          \h
                          \bye`

                          Risultato:
                          `$ \time pdftex testdim.tex
                          This is pdfTeX, Version 3.1415926-2.4-1.40.13 (TeX Live 2012)
                          restricted \write18 enabled.
                          entering extended mode
                          (./testdim.tex )
                          No pages of output.
                          Transcript written on testdim.log.
                          16.83 real 15.62 user 0.12 sys`
                          Ciao
                          Enrico

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

                      Go to top