Ottimizzazione codice, vantaggi poo

di il
60 risposte

60 Risposte - Pagina 3

  • Re: Ottimizzazione codice, vantaggi poo

    Sto cercando di capire il tuo suggerimento, ma non mi trovo su alcune cose: con queste classi l'indice con i grup_id non mi serve più?
    poi, dovrei cercare in ogni [x] di vector<Gruppi*> vecGruppi[x]; se parola1 è presente o meno, e stessa cosa devo fare con parola2, quando li trovo entrambe gli dico
     std::map<int, Parola> & GetGruppo()    {        return gruppoParole;    };
    di parola1

    e lo passo in vecGruppi[parola2] con
    const void UnisciGruppo(std::map<int, Parola> & gruppoDaUnire)
        {        gruppoParole.insert(gruppoDaUnire.begin(), gruppoDaUnire.end());    }
  • Re: Ottimizzazione codice, vantaggi poo

    Vuoi spostare una parola o tutte?
    Se uno fai Inserisci in uno ed elimina nell'altro. Se tutte fai unisci gruppo e cancella il gruppo da cui hai preso gli elementi.
  • Re: Ottimizzazione codice, vantaggi poo

    Ci pensiamo domani alla mappa del hash coi puntatori dei gruppi. Mo non connetto più. Notte
  • Re: Ottimizzazione codice, vantaggi poo

    Poi ripensandoci, non sono convinto che creare una map<hashkey,ptrId*> sia conveniente. Perchè a che dovrebbe puntare ptrId? al dato m_Id della classe Gruppo?
    Poi scusa se te lo ripeto, mi potresti spiegare col codice che hai fatto tu dove andrei a recuperare tempo, non ti sto dicendo che non va bene voglio solo capire le ottimizzazioni perchè non mi è chiaro a me, nel senso io avevo fatto una solo classe, mentre tu due, ci sono vantaggi o è solo chiarezza di codice. Per esempio quando dici
    "Vedi qualche movimentazione di groupID in quel codice? NO, perche il groupID fa parte della classe che comprende la map, quindi nell'unione non devi fare nulla. la map dentro il gruppo non sa a quale gruppo appartiene ed è giusto così.", poi dovrei aggiornare l'indice o no?
    Lo so, forse non mi sono spiegato bene e non ti ho fatto un quadro completo, ma purtroppo più che passarti il codice e dirti le operazioni che devo eseguire non saprei che fare, perchè alcuni concetti e dubbi sono anche un po' astratti per me e magari mi spiego male. Ho ancora qualche giorno a disposizione per ottimizzare, dopodichè non ti romperò più le scatole . In generale ti è chiaro il programmino o ci sono dei passaggi che devo spiegare meglio
  • Re: Ottimizzazione codice, vantaggi poo

    Infatti non è che sei molto chiaro ma cerco di capire quel che si può. Tu pensalo cosi. Ho delle scatole con dentro delle mele. Se sposto una mela da una scatola all'altra non devo assegnare un attichetta alla mela per dirli che adesso appartiene ad una nuova scatola perchè ho già la enumerazione nelle scatole. Quindi spostare una mela da scatola 1 alla 2 comporta solo lo spostamento fisico non la scrittura di tutti i codici a barre che potrebbe avere l'ettichetta sulla mela.
    Tovare poi dove si trova una mela potrei fare una ricerca alla ciecca su tutte le scatole e vedere se c'è la mela dentro oppure potrei tenere un collegamento esterno (vedi map<int,group *>) ed aggiornarlo ad ogni spostamento mele. Qui bisogna valutare cos'è più veloce: la ricerca in tutte le scatole della mela che mi serve oppure la riassegnazione delle ettichette ogni volta che sposto mele. Credo che questo sia il quadro completo giusto?
  • Re: Ottimizzazione codice, vantaggi poo

    Esatto, ecco questi esempi li capisco un pò meglio del codice . Diciamo che a rigor di logica mi sembrerebbe più veloce usare un indice, che cercare sempre in tutti i vettori, meglio poi se si riesce ad ottimizzare questo indice con dei puntatori ma ripeto non so se sia fattibile.
    Per esempio io fino ad ora ho usato sempre una map<int,int> con in secondo int che sarebbe il numero sulla scatola diciamo. Se volessi usare map<int,group *>, il group* dovrebbe puntare a qualcosa di specifico, se prima era un numero ora sarà un dato m_Id della classe gruppi? Ma sto ottimizzando qualcosa, o la memoria è sempre occupata allo stesso modo, il tempo sarà più o meno quello? Cioè io ho capito che copiare, scrivere, allocare, spostare implica ogni volta un spreco di risorse di tempo e memoria, eppure non riesco a capire dove poter guadagnare queste risorse.
  • Re: Ottimizzazione codice, vantaggi poo

    In C++ esistono queste regole
    1) Non ottimizzare mai
    2) Se proprio devi ottimizzare leggi la regola 1

    Quindi con quali dati tu hai fatto le ricrche e hai visto che perdi tempo? Hai 10000000000 stringhe con cui puoi fare delle prove? Avere una mappa con hash e puntatori a gruppi è fattibile e non costa niente durante l'inserimento singolo, ma costa tenerlo aggiornato.

    Non abbiamo parlato di compilatori: Se usi Visual Studio pre 2010 devi usare SECURE_SCL=0 nelle impostazioni compilatore in release se vuoi vedere delle velocità vere. In debug non puoi fare riferimenti alle misurazioni perche STL è concepito per avere una marea di controlli in debug ed essere ottimizzato al massimo in release. Quindi non vorrei stessi facendo delle seghe mentali inutili.

    http://www.flounder.com/optimization.ht
  • Re: Ottimizzazione codice, vantaggi poo

    Ok non bisogna ottimizzare, ma devo cercare di cambiare impostazione per renderlo più veloce, non so se dica ottimizzazione o in altro modo, e non sto dicendo che usare un indice sia il metodo migliore, ma per le mie conoscenze fin'ora non sono riuscito a fare di meglio, appunto chiedevo se c'erano dei metodi per gestire il tutto con le classi e se era meglio o uguale, o se stavo facendo delle copie/spostamenti inutile che potevo evitare. Sto provando ad aggiornare l'indice con i puntatori, ma non riesco a farlo dinamicamente nel senso, bisogna andare ad aggiornare lo stesso il puntatore con il nuovo indirizzo. Se ho
    map<hahskey1, gruppo1*>
    map<hahskey2, gruppo1*>
    map<hahskey3, gruppo2*>
    e devo spostare hashkey1 e hahskey2 in hahskey3, non gli posso dire direttamente gruppo1* ora punta a gruppo2*, con un solo comando invece di andare ad aggiornarli uno alla volta?
  • Re: Ottimizzazione codice, vantaggi poo

    Per ogni spostamento che fai devi aggiornare il valore quindi non c'è un commando che te li sposta in un colpo solo. Quindi per quello ti chiedo: sei sicuro che ne valga la pena farlo e non andare avanti col la ricerca ciecca? Hai mille gruppi di 1 milione di stringhe ciascuna. La ricerca ciecca ti fa 1000 * log(1milione) comparazioni.
    Devi spostare 1 milione di puntatori da un gruppo all'altro: devi fare 1 milione di assegnamenti (inserimenti) nel nuovo gruppo. Morale 1000 * log(1 milione) = 1000 * 14 = 14000 che è molto minore di 1 milione di spostamenti. Quindi adesso hai ancora più dubbi

    Non mi hai risposto sul compilatore.
  • Re: Ottimizzazione codice, vantaggi poo

    Per quanto riguarda le misurazioni non lo dico io ma si carica il programma su una pagina web e ci dice il tempo di esecuzione, ora sono sui 60 secondi ma dovrei scendere di 3/4 volte.
    Per quanto riguarda la ricerca cieca, in effetti hai ragione, anche se non hai specificato che se conti log(n) vuol dire che usi una map o un set, quindi anche i tempo di inserimento sono log(n) e la cancellazione, e non costanti come in un vettore.
    Infatti avevo già provato vettor<set<hashkey>> (che mi ha restituito correct, era giusto il procedimento) ma mi ha tenuto come tempo migliore quello di un vector<vector<int>> che era circa sugli 80sec. Poi ho provato con l'indice e sono sceso a 60sec. Ma ripeto si potrebbe migliorare ancora di parecchio, solo che non capisco dove vado a perdere tempo.
  • Re: Ottimizzazione codice, vantaggi poo

    Programma completo
    #include <iostream>
    #include <sstream>
    #include <vector>
    #include <string>
    #include <map>
    #include <memory>
    
    using namespace std;
    
    class Parola
    {
    public:
    	Parola(const std::string & str = "")
    		: m_string(str)
    		, m_hash(funzHash(str))
    	{
    
    	};
    	const int GetHash() const { return m_hash; };
    	const std::string & GetString() const { return m_string; };
    	static const int funzHash(const std::string & parolaHash)
    	{
    		int h = 5381;
    		const size_t size = parolaHash.size();
    		for (size_t i = 0; i < size; ++i)
    		{
    			h = h * 33 + parolaHash[i];
    		}
    		h = abs(h);
    		return h;
    	}
    private:
    	std::string m_string;
    	int m_hash;
    };
    
    
    class Gruppi
    {
    	std::map<int, Parola> gruppoParole;
    public:
    	Gruppi(const int _id) : m_ID(_id) , m_globalSize(0){};
    	~Gruppi(){};
    	const int GetGroupID() const { return m_ID; };
    	const size_t GetGroupSize() const { return gruppoParole.size(); };
    	const size_t GetGroupGlobalSize() const { return m_globalSize; };
    	const void SetGroupID(const int & groupID){ m_ID = groupID; };
    	std::map<int, Parola> & GetGruppo() { return gruppoParole; };
    	const bool InserisciParola(const std::string & parola)
    	{
    		const int hash = Parola::funzHash(parola);
    		std::map<int, Parola>::const_iterator it = gruppoParole.find(hash);
    		if (it == gruppoParole.end())
    		{
    			Parola nuovaParola(parola);
    			gruppoParole[hash] = nuovaParola;
    			m_globalSize += parola.size();
    			return true;
    		}
    		return false;
    	}
    
    	const bool InserisciParola(const Parola & parola)
    	{
    		std::map<int, Parola>::const_iterator it = gruppoParole.find(parola.GetHash());
    		if (it == gruppoParole.end())
    		{
    			gruppoParole[parola.GetHash()] = parola;
    			m_globalSize += parola.GetString().size();
    			return true;
    		}
    		return false;
    	}
    	const bool CercaParola(const std::string & parola)
    	{
    		return CercaParola(Parola::funzHash(parola));
    	}
    
    	const bool CercaParola(const int & parolaHash)
    	{
    		return (gruppoParole.find(parolaHash) != gruppoParole.end());
    	}
    
    	const bool EliminaParola(const std::string & parola)
    	{
    		return EliminaParola(Parola::funzHash(parola));
    	}
    
    	const bool EliminaParola(const int & parolaHash)
    	{
    		std::map<int, Parola>::const_iterator it = gruppoParole.find(parolaHash);
    		if (it != gruppoParole.end())
    		{
    			m_globalSize -= it->second.GetString().size();
    			gruppoParole.erase(it);
    			return true;
    		}
    		return false;
    	}
    
    	const void UnisciGruppo(Gruppi & gruppo)
    	{
    		m_globalSize += gruppo.GetGroupGlobalSize();
    		std::map<int, Parola> &g = gruppo.GetGruppo();
    		gruppoParole.insert(g.begin(), g.end());
    	}
    
    	void Svuota()
    	{
    		gruppoParole.clear();
    		m_globalSize = 0;
    	}
    
    private:
    	int m_ID;
    	size_t m_globalSize;
    };
    
    
    int main()
    {
    	std::vector<Gruppi *> vettoreGruppi;
    	std::map<int, Gruppi *> mapHash;
    	
    	string input, parola, parola2;
    	int dimCoda = 0, b = 0;
    	char s;
    
    	while (input != "<END>")    
    	{
    		getline(cin, input);
    		stringstream ssin(input);
    		s = 0, parola = "", parola2 = "";
    		ssin >> s;
    
    		switch (s)
    		{
    			case 'e':
    			{
    				while (ssin >> parola)
    				{
    					Parola p(parola);
    					if (mapHash.find(p.GetHash()) == mapHash.end())
    					{
    						Gruppi *g = new Gruppi(vettoreGruppi.size());
    						if (g->InserisciParola(p))
    						{
    							mapHash[p.GetHash()] = g;
    							vettoreGruppi.push_back(g);
    						}
    					}
    					
    				}
    			}
    			break;
    			case 'u':
    			{
    				std::string s1, s2;
    				ssin >> s1 >> s2;
    				const int hash1 = Parola::funzHash(s1);
    				const int hash2 = Parola::funzHash(s2);
    				std::map<int, Gruppi *>::const_iterator it1, it2;
    				it1 = mapHash.find(hash1);
    				it2 = mapHash.find(hash2);
    				if ((it1 != mapHash.end()) && (it2 != mapHash.end()))
    				{
    					it1->second->UnisciGruppo(*(it2->second));
    					for (std::map<int, Gruppi *>::iterator it = mapHash.begin(); it != mapHash.end(); ++it)
    					{
    						if (it->second == it2->second)
    						{
    							it->second = it1->second;
    						}
    					}
    					it2->second->Svuota();
    				}
    			}
    			break;
    			case 'm':
    			{
    						std::string s1, s2;
    						ssin >> s1 >> s2;
    						const int hash1 = Parola::funzHash(s1);
    						const int hash2 = Parola::funzHash(s2);
    						std::map<int, Gruppi *>::iterator it1;
    						std::map<int, Gruppi *>::const_iterator it2;
    						it1 = mapHash.find(hash1);
    						it2 = mapHash.find(hash2);
    						if ((it1 != mapHash.end()) && (it2 != mapHash.end()))
    						{
    							it2->second->InserisciParola(s1);
    							it1->second->EliminaParola(s1);
    							it1->second = it2->second;
    						}
    			}
    			break;
    			case 's':
    			{
    						std::string s1;
    						ssin >> s1;
    						const int hash1 = Parola::funzHash(s1);
    						std::map<int, Gruppi *>::iterator it1;
    						it1 = mapHash.find(hash1);
    						if (it1 != mapHash.end())
    						{
    							std::cout << it1->second->GetGroupSize() << " - " << it1->second->GetGroupGlobalSize() << std::endl;
    						}
    			}
    			break;
    		}
    	}
    	return 0;
    }
    Prova e dimmi come va.

    p.s.: Devi liberare la memoria allocata con new. Non ho avuto il tempo a farlo.
  • Re: Ottimizzazione codice, vantaggi poo

    Allora ho aggiunto il caso i che mancava, praticamente quando ho i vuol dire che è come se ricominciassi da capo, devo svuotare i vettore e prepararmi per nuovi gruppi con nuove stringhe
    
    case 'i':
            {
                vettoreGruppi.clear();
                mapHash.clear();
            }
    
    poi per quanto riguarda il deallocare la memoria di new, non si dealloca da solo alla fine del suo scope? ho provato con delete g, ma non so se intendevi questo.
    Gruppi *g = new Gruppi(vettoreGruppi.size());
                        if (g->InserisciParola(p))
                        {
                            mapHash[p.GetHash()] = g;
                            vettoreGruppi.push_back(g);
                        }
                        delete g;
    Ultima cosa, sembra ci siano problemi con il caso u(unione), quando lo eseguo mi ritorna tutti e due i gruppi con 0
  • Re: Ottimizzazione codice, vantaggi poo

    La deallocazione lo fai fuori dal ciclo while con
    
    for (std::map<int, Gruppi *>::iterator it = mapHash.begin(); it != mapHash.end(); ++it)
            delete it->second;
    
  • Re: Ottimizzazione codice, vantaggi poo

    Manca solo questa modifica praticamente, dopo il primo
    if(it->second == it1->second)
    it1->second mi diventà automaticamente come it2->second, e quindi quando continua il ciclo for, questa condizione
    if (it->second == it1->second)
    non la verificherà più perchè it1->second è cambiato(diventato it2->second) :
    
    if ((it1 != mapHash.end()) && (it2 != mapHash.end()))
                {
                    it2->second->UnisciGruppo(*(it1->second));
                    it1->second->Svuota();
    
                    for (std::map<int, Gruppi *>::iterator it = mapHash.begin(); it != mapHash.end(); ++it)
                    {
                        if (it->second == it1->second)
                        {
                          it->second = it2->second;
                        }
                    }
                }
    
    ho provato a salvare in un int temporaneo it1->second->GetGroupID(), ma mi crasha sull'assegnamento. Come posso risolvere?
  • Re: Ottimizzazione codice, vantaggi poo

    ninjo ha scritto:


    Ultima cosa, sembra ci siano problemi con il caso u(unione), quando lo eseguo mi ritorna tutti e due i gruppi con 0
    Hai degli esempi da farmi provare?
Devi accedere o registrarti per scrivere nel forum
60 risposte