Velocizzazione analisi dati e logica del programma

di il
10 risposte

Velocizzazione analisi dati e logica del programma

Salve a tutti! ho un problema con un programma in c++:
Immaginate di avere 2 cartelle (C1 e C2) diverse, ognuna di queste contiene 200 file di testo, e ogni file di testo contiene 10.000 dati in colonna. Ogni dato di ogni file della C1 deve essere confrontato con tutti i dati della C2.
il programma in se non è molto difficile da fare, (l'ho già fatto), bastano un paio cicli e per ogni elemento di un file di C1 ti controlla tutti gli altri di C2 uno per uno.
Il problema è che utilizzando questa logica ci mette veramente tanto, più di 2 giorni a completare l'analisi di una sola coppia di cartelle!
Avete per caso qualche nuova idea per poter velocizzare il programma o qualche altre idea sul tipo di logica che devo utilizzare per questo genere di analisi?
Grazie a tutti =)

10 Risposte

  • Re: Velocizzazione analisi dati e logica del programma

    Dipende dal tipo di confronto che vuoi fare. Se vuoi confrontare se un dato è presente nell'altro il metodo + veloce è quello di inserire i dati del C1 in un std::vector e confrontare un dato del C2 nel vettore con binary_search. Se poi devi anche elaborare il confronto c'è la possibiltà di implementare una funzione di confronto mettendo i valori in una std::map.

    esempio binary_search
    http://www.cplusplus.com/reference/algorithm/binary_search/
  • Re: Velocizzazione analisi dati e logica del programma

    Ok grazie!
    il tipo di confronto è il seguente: l'elemento di C1 deve essere sottratto all'elemento "i-esimo" di C2, se la differenza è minore di un certo valore allora il programma mi genera un file con il valore della differenza e i valori dei due elementi di C1 e C2..
  • Re: Velocizzazione analisi dati e logica del programma

    Allora può funzionare con equal_range.
    
    static int differenza = 3 //numero preso a caso.
    bool mygreater (int i,int j) { return (i-j<differenza); }
    
    int main () {
      int myints[] = {10,20,30,30,20,10,10,20}; 
      vector<int> v(myints,myints+8);                         // 10 20 30 30 20 10 10 20 //questo è il tuo C1
      pair<vector<int>::iterator,vector<int>::iterator> bounds;
    
       // using "mygreater" as comp:
      sort (v.begin(), v.end(), mygreater);                   // 30 30 20 20 20 10 10 10 //questo è il sort
      bounds=equal_range (v.begin(), v.end(), datoC2, mygreater); //       ^        ^
    
      //adesso bounds contiene un vettore con dati che soddisfano la funzione mygreater
     //puoi usarli questi dati x scriverli su file dov'è l'inizio dei dati è bounds.first e la fine dei dati che soddisfano è bounds.second. 
    //for(it = bounds.first; it != bounds.second; ++it)
    cout << *it << datoC1 << *it - datoC2;
    
      return 0;
    }
    
  • Re: Velocizzazione analisi dati e logica del programma

    La complessità sarà 2*log(n)*m e non + m*n. Un po di vantaggio l'avrai di sicuro.
  • Re: Velocizzazione analisi dati e logica del programma

    Soluzione finale. Tempo ricerca 0 secondi. Tempo visualisazione dati 6 secondi (10000 x 10000 ricerche), oppure 57 secondi (100000 x 100000 ricerche). Come vedi il tempo maggiore lo consumi visualizzando i dati che cercandoli.
    
    int main(void)
    {
    	const int _diffValue = 3;
    	time_t start,end;
    	std::vector<int> vec1;
    	std::vector<int> vec2;
    
    	std::vector<int>::iterator it1;
    	std::vector<int>::iterator it2begin,it2end,it2;
    
    	int i = 0;
    	for(i = 0; i < 100000; i++)
    	{
    		vec1.push_back(i);
    		vec2.push_back(2*i);
    	}
    	
    
    	int diff = 0;
    	time(&start);
    	std::ostream_iterator<int> itOut(std::cout, " ");
    	sort(vec2.begin(),vec2.end());
    	for(it1 = vec1.begin(); it1 != vec1.end(); ++it1)
    	{
    		it2begin = std::lower_bound(vec2.begin(), vec2.end(), *it1 - _diffValue + 1);
    		it2end = std::upper_bound(vec2.begin(), vec2.end(), *it1 + _diffValue - 1);
    		for(it2 = it2begin; it2 != it2end; ++it2)
    			cout << *it1 << " " << *it2 << " " << abs(*it1 - *it2) << endl;
    	}
    	time(&end);
    	double timeDiff = difftime(end,start);
    	cout << "Took " << timeDiff << " seconds!" << endl;
    	cin.get();
    	return 0;
    } 
    
  • Re: Velocizzazione analisi dati e logica del programma

    Ok grazie! ma occorrono particolari librerie per i vettori? non è che potresti inserire qualche commento nel programma? perché ci sono alcuni passaggi che non mi son tanto chiari..
    grazie ancora..=)
  • Re: Velocizzazione analisi dati e logica del programma

    Ah...un'ultima cosa: come faccio ad assegnare a vec1 o a vec2 la variabile del file in esame?..cioè, il programma come fa ad associare a vec1 e a vec2 la "colonna" del file di dati?...
    ad esempio:
    [color=#0000BF]
              .............
              ifstream IN1("dati.dat", ios::in);
              ifstream IN2("dati2.dat", ios::in);
              IN1 >>a>>b>>c;
              IN2 >>a2>>b2>>c2;
              std::vector<int> vec1;
              std::vector<int> vec2;
              .................[/color]
    come faccio a far si che vec1 sia ad esempio uguale alla "colonna dati" a e vec2 alla "colonna dati" a2?
  • Re: Velocizzazione analisi dati e logica del programma

    Ti mando il programma completo così vedi anche gli include vari. in sostanza x inserire dei dati i vettori hanno la funzione push_back.
    
    #include <vector>
    #include <iostream>
    #include <fstream>
    #include <time.h>
    #include <algorithm>
    using namespace std;
    
    
    int main(void)
    {
    	const int _diffValue = 3;
    	time_t start,end;
    	std::vector<int> vec1;
    	std::vector<int> vec2;
    
    	std::vector<int>::iterator it1;
    	std::vector<int>::iterator it2begin,it2end,it2;
    	
    	/* questo è il tuo esempio.
        ifstream IN1("dati.dat", ios::in);
        ifstream IN2("dati2.dat", ios::in);
    
    	int a = 0;
    	while(IN1.good())
    	{
    		IN1 >> a;
    		vec1.push_back(a);
    	}*/
    
    	int i = 0;
    	for(i = 0; i < 100000; i++)
    	{
    		vec1.push_back(i);
    		vec2.push_back(2*i);
    	}
    	
    
    	int diff = 0;
    	time(&start);
    	sort(vec2.begin(),vec2.end());
    	for(it1 = vec1.begin(); it1 != vec1.end(); ++it1)
    	{
    		it2begin = std::lower_bound(vec2.begin(), vec2.end(), *it1 - _diffValue + 1);
    		it2end = std::upper_bound(vec2.begin(), vec2.end(), *it1 + _diffValue - 1);
    		for(it2 = it2begin; it2 != it2end; ++it2)
    			cout << *it1 << " " << *it2 << " " << abs(*it1 - *it2) << endl;
    	}
    	time(&end);
    	double timeDiff = difftime(end,start);
    	cout << "Took " << timeDiff << " seconds!" << endl;
    	cin.get();
    	return 0;
    } 
    
    lower_bound cerca il valore + piccolo rispetto a quello inserito. upper_bound il + grande. avendo le due posizioni (siccome il vettore e stato ordinato tramite sort) puoi sapere il range dei dati che soddisfano i tui criteri.
  • Re: Velocizzazione analisi dati e logica del programma

    Ok perfetto grazie mille funziona!! solo 2 ultimi chiarimenti:
    questa logica utilizzata è come se facesse svolgere "in parallelo" i calcoli al programma anziché farglieli svolgere "in serie" come faceva prima col mio algoritmo, giusto?...la costante
    const int _diffValue = 3; è il valore della differenza che gli voglio dare io arbitrariamente?
  • Re: Velocizzazione analisi dati e logica del programma

    Si giusto. I pratica x ogni valore lui ti trova automaticamente il range risparmiandoti del tempo. Infatti anche con vettori da 100000 elementi la ricerca è pressoche immediata. _diffValue e la differenza che tu vuoi dare. C'è un altra miglioria da fare però. Invece di usare i vettori puoi usare il std::set che è già ordinato e contiene le funzioni lower_bound e upper_bound all'interno così la ricerca è ancora + veloce.
Devi accedere o registrarti per scrivere nel forum
10 risposte