Re: [C++] Differenza di prestazioni con implementazioni simili

Messaggioda utente__medio » 11/12/2021, 00:17

vict85 ha scritto:Per trovare i coefficienti si può usare penso una ricerca binaria. Siccome moltiplicazione e confronto hanno peso \( (O(n_b) \) e la ricerca ha un costo \( O(\log_2(b)) \) allora il costo è \( O(\log_2(b)n_b) \).D'altra parte \( n_{10^9} = 9^{-1} n_{10} \) e \( \log_2(10^9) = 9\log_2(10) \), quindi mi sembra che il calcolo del coefficiente ha complessità costante al cambio della base. Però il numero di coefficienti dovrebbe essere 9 volte più piccolo, e così anche la sottrazione. Quindi mi aspetterei performance migliori al crescere della base.

Purtroppo so poco o nulla di teoria della complessità computazionale, ma in linea di massima credo di aver capito quello che intendi dire. In ogni caso non so quanto lo scenario generale da te prospettato possa applicarsi nello specifico ai due algoritmi che ho implementato.

Se può essere utile provo a descriverli per sommi capi:

1) nel vecchio algoritmo con le stringhe, opero la classica divisione in base $10$.
Per esempio:

$\overbrace{\underbrace{34}_(a_1)\underbrace{5}_(r_3)201}^R8743566:\overbrace{\underbrace{8}_(d_1)7154}^D$

- se $R<D$ allora $q_i=0$ e $R=R$ (ovviamente poi $R$ "avanza" lungo il dividendo);

- se $R=D$ allora $q_i=1$ e $R=0$;

- altrimenti (ossia $R>D$) $q_iin[1;q_(i,max)]=[1;a_1//d_1]$ e $R=R-q_i*D$.
Per determinare $q_i$ parto da un valore di primo tentativo pari a $q_(i,T)=q_(i,max)$ a scendere. Per testare $q_(i,T)$ non vado a fare il calcolo per intero verificando che $R<=q_(i,T)*D$, ma avanzo una cifra alla volta.
Cerco di spiegare meglio quello che intendo... detti $b_i=q_(i,T)*d_i$ e $a_i=(a_(i-1)-b_(i-1))*10+r_(i+2)$:
* se $a_i<b_i$, allora deduco che $q_(i,T)>q_i$ e diminuisco $q_(i,T)$ di un'unità;
* se $a_i-b_i>=q_(i,T)$, allora deduco che $q_i=q_(i,T)$.

Riprendendo l'esempio numerico sopra postato per la determinazione di $q_1$ si ha:
# $q_(1,T)=a_1//d_1=34//8=4$ :
## $a_1=34$ e $b_1=q_(1,T)*d_1=4*8=32$, essendo $a_1>b_1$ $\wedge$ $a_1-b_1<q_(1,T)$ continuo;
## $a_2=(a_1-b_1)*10+r_3=25$ e $b_2=q_(1,T)*d_2=4*7=28$, essendo $a_2<b_2$ diminuisco $q_(1,T)$;
# $q_(1,T)=4-1=3$ :
## $a_1=34$ e $b_1=q_(1,T)*d_1=3*8=24$, essendo $a_1-b_1>q_(1,T)$ posso concludere che $q_1=3$.

------------------------------------------------------------------------------------

2) nel nuovo algoritmo con i vettori di bool (lo so, nello specifico utilizzo vector<bitset<32>>, ma ai fini della spiegazione meglio parlare in termini di vector<bool>), opero invece la divisione direttamente in base $2$:

- se $R<D$ allora $q_i=0$ e $R=R$;

- altrimenti $q_i=1$ e $R=R-D$.

Per esempio:

$\overbrace{110100}^R10001010$ $:$ $=>q_1=0$
$\underbrace{111001}_D$


$\overbrace{1101001}^R0001010$ $:$ $=>q_2=1$
$\text{_}\underbrace{111001}_D$


$0\overbrace{1100000}^R001010$ $:$ $=>q_3=1$ $...$
$\text{__}\underbrace{111001}_D$


$R<D$ si verifica quando $R$ ha lo stesso numero di cifre di $D$ e partendo da sinistra la prima coppia di cifre corrispondenti diverse presenta un $1$ in $D$.

Per la sottrazione invece mi limito, partendo da destra, ad invertire, per ogni bit di $R$ in corrispondenza di un $1$ in $D$, i bit di $R$ finché andando verso sinistra non incontro un $1$.

------------------------------------------------------------------------------------

Detto ciò, è vero che il vettore di bool è circa 3,3 volte più lungo della stringa, ma nella versione con le stringhe ci sono varie operazioni con interi che internamente operano comunque su sequenza di più bit, senza dimenticare poi la parte relativa ai "tentativi".
Probabilmente non mi resta che arrendermi all'evidenza, ma nella mia ignoranza trovo questa differenza nelle prestazioni abbastanza controintuitiva.
"Ci abbaiano, Sancho; segno che stiamo cavalcando!"
utente__medio
Junior Member
Junior Member
 
Messaggio: 36 di 394
Iscritto il: 02/11/2021, 12:48
Località: Draghistan

Re: [C++] Differenza di prestazioni con implementazioni simili

Messaggioda apatriarca » 12/12/2021, 23:58

Questo thread sta diventando molto lungo e credo sia opportuno fare due piccoli commenti:
1. Quando si inizia a lavorare su algoritmi più o meno complicati una comprensione (almeno di base) sulla complessità computazionali è molto utile.
2. In questo forum non siamo certamente esperti di questo genere di algoritmi, ma esistono diversi articoli e qualche libro che descrive algoritmi per questo genere di operazioni. Un punto di partenza potrebbe essere quello di guardare una libreria come GMP che descrive che algoritmi usano: https://gmplib.org/manual/Algorithms.
3. Siccome l'implementazione ottimale per determinati processori non è necessariamente la stessa per altri, libreria come GMP fanno uso di implementazioni diverse in base al sistema.
apatriarca
Moderatore
Moderatore
 
Messaggio: 5640 di 10436
Iscritto il: 08/12/2008, 20:37
Località: Madrid

Re: [C++] Differenza di prestazioni con implementazioni simili

Messaggioda utente__medio » 13/12/2021, 13:18

apatriarca ha scritto:Un punto di partenza potrebbe essere quello di guardare una libreria come GMP che descrive che algoritmi usano: https://gmplib.org/manual/Algorithms.

Ottimo, appena possibile gli darò un'occhiata.

Grazie comunque per i vari consigli che mi avete dato!
"Ci abbaiano, Sancho; segno che stiamo cavalcando!"
utente__medio
Junior Member
Junior Member
 
Messaggio: 38 di 394
Iscritto il: 02/11/2021, 12:48
Località: Draghistan

Precedente

Torna a Informatica

Chi c’è in linea

Visitano il forum: Nessuno e 1 ospite