Curiosità su velocita

di il
19 risposte

Curiosità su velocita

Salve a tutti 

siccome sono un tipo curioso mi chiedevo se in fase di esecuzione è piu veloce fare un ciclo for per azzerare una variabile di tipo char*

o fare la chiama ad una funzione che faccia il ciclo di azzeramento della variabile passando naturalmente il nome della variabile e la lunghezza.

naturalmente se la variabile è una sola non ci sarebbe guadagno ma con più variabili c'è un minimo di guadagno oppure no?

l'unica cosa certa è che il listato sarebbe più leggibile! 

19 Risposte

  • Re: Curiosità su velocita

    Se parliamo di un buffer, ovviamente si usa un ciclo.

  • Re: Curiosità su velocita

    certo che si parla di un buffer e si usa un ciclo 
    ma per esempio è più veloce
    {
    char abc[10],def[20],ghi[30],lmn[40];
    int a;
    // prima opzione
    //--------------------
    
    for (a=0;a<10;a++)
    { abc[a]=' '; }
    for (a=0;a<20;a++)
    { def[a]=' '; }
    for (a=0;a<30;a++)
    { ghi[a]=' '; }
    for (a=0;a<30;a++)
    { lmn[a]=' '; }
    }
    
    // seconda opzione
    //------------------
    {
    Cancella_variabile (abc,10);
    Cancella_variabile (def,20);
    Cancella_variabile (ghi,30);
    Cancella_variabile (lmn,40);
    }
    void Cancella_variabile(char *beffer, int lun)
    {
      int a;
      for (a=0;a<10;a++)
      { buffer[a]=' '; }
    }
    ad una cosa del genere mi riferivo!
  • Re: Curiosità su velocita

    Ovviamente senza le chiamate a funzione è più veloce ma solo se parliamo di migliaia o milioni di chiamate.

  • Re: Curiosità su velocita

    Giusto il numero delle chiamate però non centra nulla!

    per tutti coloro che sono interessati al perchè parlo per i neofiti e per i curiosi come me!

    il motivo è:

    la prima opzione:  accede direttamente alla memoria, buffer o variabile, semplice ciclo! 

    la seconda opzione:  deve prima mettere l'indirizzo e il valore nello stack e poi fare la chiamata alla funzione. 

    la funzione una volta chiamata deve prendere i dati dallo stack e poi accedere alla memoria per effettuare l'operazione!

    naturamelmente i tempi sono talmente esigui che manco con 1.000.000 di chiamate alla funzione si noterebbe la differenza!

    P.S.

    Naturalmente vale per qualsiasi tipo di vettore alias buffer! 

    per i tipi strutturati, seppur più lenta, consiglio la soluzione 2 perchè è più ordinata è fa capire meglio i listati!

  • Re: Curiosità su velocita

    26/01/2024 - smalldragon ha scritto:


    Giusto il numero delle chiamate però non centra nulla!

    Come non c'entra? Che dici?

    Comunque ricordati che i dati non sono passati ma solo i puntatori che sono pochi byte nello stack, in seguito l'accesso in memoria è il medesimo tra i due codici.

    Anche nel caso di strutture non cambia nulla, anche in questo caso non passano dati ma puntatori. 

  • Re: Curiosità su velocita

    Ovvio che viene passato il puntatore per ogni tipo!

    anche se negli esempi che ho messo viene passato un puntatore ed un valore!

    lo so che non cambia niente anche per le strutture ma cosi come ho scritto è meglio la soluzione 2,in questo caso, solo per comprendere meglio i listati e per una questione di ordine e soprattutto si risparmia carta in fase di stampa!

    è tra perdere qualche milliardesimo di secondo in fase di elaborazione e la chiarezza del listato preferisco e consiglio la chiarezza del listato!

    P.s. il numero delle chiamate non c'entra nulla perchè nel caso 2 ci sono 6 istruzioni macchina in più come minimo, nell'esempio che ho postato, in più che seppur hanno un coso infinetimale e ridicolo in termini di tempo hanno comunque un costo che l'opzione 1 non ha è che non potrà mai eguagliare!  

  • Re: Curiosità su velocita

    26/01/2024 - smalldragon ha scritto:


    il numero delle chiamate non c'entra nulla perchè

    Come sempre non ci capiamo. Le chiamate a funzione impegnano stack all'ingresso e all'uscita quindi è ovvio che introducono un overhead rispetto al codice senza chiamate. 

    In ogni caso, per questi compiti (quando veramente servono) si usa la funzione di libreria

    memset

    o le equivalenti macro di Windows

    ZeroMemory 

    FillMemory

    P.S. non usare punti esclamativi ! non servono…

  • Re: Curiosità su velocita

    Ok me ne ricordero di non usarli gli esclamativi

  • Re: Curiosità su velocita

    @smalldragon, ti dimentichi l'attore PRINCIPALE: IL COMPILATORE!

    Con le sue belle regole di ottimizzazione. Fino a che non decompili il binario, non saprai mai come il compilatore ha deciso di implementare quella particolare funzionalita'. Magari ha messo direttamente il codice e non usa nessuna funzione!

    Inoltre, se chiamare la funzione memset o fare il ciclo, DIPENDE da quanti byte devi cancellare. Spannometricamente, dai 8 in su, stai certo che la memset batte il ciclo.

  • Re: Curiosità su velocita

    Anche perché poi il compilatore userà singole istruzioni assembly come

    REP STOSB

    REP STOSW

    REP STOSD

    che trattano l'intero buffer

  • Re: Curiosità su velocita

    Beh si discuteva se conveniva più fare un ciclo o chiamare una funzione apposita per cancellare un buffer!

    vedi l'esempio che ho postato cosi  comprendi meglio.

    la memset sarà sicuramente più veloce della funzione che ho scritto io su questo non ho dubbi ma comunque è una funzione!

    e se al compilatore si dice chiama la funzione x che lui sia daccordo o meno la chiamerà.

    altrimenti se il compilatore fa quello che vuole

    non ci resterebbe che collegare il cervello al computer e digli fammi un programma che risolva questo problema e lui farebbe tutto il lavoro.

    il che al momento, che io sappia, è impossibile forse in futuro.

    ma leverebbe lo sfizio di programmare non trovi? 

    ma come dicevo nel post era semplice curiosità!

  • Re: Curiosità su velocita

    Memset non è una funzione nel senso ordinario: il compilatore caricherà un valore su un registro e lo passerà su tutta la zona di memoria interessata. Lo stack non viene toccato. Puoi controllare sul disassembly cosa fa il compilatore 

    Dato che gli array sono contigui, puoi utilizzare anche un solo memset

    In generale i cicli sono un male nell'ottimizzazione per tempo: devi fare sempre il “loop unrolling” se possibile (se hai un ciclo di quaranta istruzioni, fai copia e incolla quaranta volte invece di fare un ciclo). Anche le chiamate a funzione sono un male perché si perde tempo ad aggiornare lo stack

    L'ottimizzazione temporale è un argomento interessante e vale la pena studiarlo, ma giustamente, come hai detto, va usata solo quando realmente necessaria

  • Re: Curiosità su velocita

    26/01/2024 - smalldragon ha scritto:


    e se al compilatore si dice chiama la funzione x che lui sia daccordo o meno la chiamerà.

    Non è così. Se sono attive ottimizzazioni spinte, il compilatore potrebbe decidere altrimenti

    altrimenti se il compilatore fa quello che vuole

    È esattamente così. Del resto il compilatore è esso stesso un programma e tu non sai esattamente cosa faccia in certe situazioni.

    SE disabiliti le ottimizzazioni, le cose andranno in maniera più prevedibile. 

  • Re: Curiosità su velocita

    Grazie weierstrass non sapevo che il compilatore perdesse tempo a ragruppare tutti i vettori e le matrici e poi le variabili per dargli un ordine.

    per oregon va bene che il compilatore fa quello che vuole in fase di ottimizzazione,anche mettere sotto altra forma la funzione o il codice scritto, ma comunque deve rispettare ciò che il programma gli dice di conseguenza se il programma gli dice chiama la funzione x lui, il compilatore lo farà. 

Devi accedere o registrarti per scrivere nel forum
19 risposte