Objektorientiert und OpenMP?



  • Hey Leute, ich habe da ein kleines Problem. Ich soll ein Programm schreiben das einen String-Matching Algorithmus implementiert. Es handelt sich um den Horspool falls das was sagt/hilft. Ich habe den Horspool Objektorientiert angelegt und er läuft auch Problemlos. Wobei ich glaube das er ein wenig langsam ist. Nun soll das ganze mit OMP Parallel programmiert werden. Aber irgendwie will das Programm nicht ganz so wie ich will. Ich dachte mir, ich teile die Datei in der das Pattern gesucht werden soll in die Anzahl von Teilen, wie ich Threads erstellen möchte. Jeder Teil der Datei(Thread) ist ein eigenes Objekt. Dann rufe ich über eine for-Schleife für jedes Objekt eine Funktion des Objektes auf in der der Horspool eigentlich durchgeführt wird. Allerdings will das ganze einfach nicht parallel laufen. Ich bekomme immer die gleiche Zeit. Könnt ihr mir bitte helfen?
    Ich hänge euch mal meinen Code mit an.

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <vector>
    #include <algorithm>
    #include <iostream>
    #include <fstream>
    #include <map>
    #include <omp.h>
    using namespace std;
    ifstream::pos_type size;
    
    //For Horspool       
    class Search {
                    static const int MAXCHAR = 256;
    				map<char,int> d;
                    int m;
                    char* patt;
                    int count;
                    vector<int>hits ;
            public:
                    Search(char*);
                    int find(char*,int,int);
                    int get_count();
                    vector<int> get_hits();
    };
    
    int Search::get_count()
    {
      return count;
    }        
    
    vector <int> Search::get_hits()
    {
       return hits;
    }
    
    Search::Search(char* p)
            {
    
    			count = 0;
    			patt = p;
                    m = strlen(patt);
    
                    int k = 0;
    
    		 for (k = 0; k < MAXCHAR; k++)
    		      d[k] = m;
    
                    for (k = 0; k < m - 1; k++){
    		  if(d.find(patt[k])==d.end()||d[patt[k]]>m-k-1)
    		    d[patt[k]] = m - k - 1;
    		}      
            }
    
    int Search::find(char* text,int start,int end)
    {
    	if(start>0)
    		start +=1;
    
    	  int n =end; 
    
    	  if (m > end-start)
    			return 0;
    
          int k = start+(m - 1);
    
    		while (k < n) {
    
    		        int j = m - 1;
                            int i = k;
    
    			 while (j >= 0 && text[i] == patt[j]) {
                                    j--;
                                    i--;
                            }
    
                            if (j < 0)
    			  {
    			    hits.push_back(i + 1);
    			    count++;
    			  }
    
    			  k += d[text[k]];
    
             }
    
    		return 0;
    
    }
    
    //Load File
    bool loadText(vector<char> &text, char* fileName)
    {
        // open file in binary and read-only mode 
        // and set file pointer to the end
        ifstream file(fileName, ios::in | ios::binary | ios::ate);
        if (!file.is_open())
            return false;
    
        // file pointer position is equal to file size
        // ifstream::pos_type 
    size = file.tellg();
         // resize string buffer
        text.resize(size);
    
        // go to file begin and read complete file
        file.seekg(0, ios::beg);
        file.read(&text[0], size);
        file.close();
    
        return true;
    }
    bool createFile(vector<int> &hits, char* filename ){
    
      ofstream outfile;
      outfile.open(filename, ios::out | ios::trunc);
      if(!outfile.is_open())
    	  return false;
      for(int i=0; i<hits.size(); ++i)
    	   outfile << (hits[i])<<endl;
    
      outfile.close();
      return true;
    }
    
    int main(int argc, char *argv[]) {
    
    if (argc < 5)
        {
            cerr << argv[0] << " <TEXTFILE> <PATTERN 1> <NMBR OF THREADS> <OUTPUTFILE>" << endl;
            return 0;
        }
    
    	vector<char> text;
        if (!loadText(text, argv[1]))
        {
            cerr << "Could not open text file." << endl;
            return 1;
        }
    
        vector<Search*> SearchObjects;
        int nmbr_of_threads = atoi(argv[3]);
        vector<int> cuts;
    
        for(int h=0;h<=nmbr_of_threads;h++)
          {
    		cuts.push_back((int)(size*((double)((double)h/(double)nmbr_of_threads))));
          }
    
        for(int h=0;h<2*nmbr_of_threads-1;h++)
          {
    	Search *newSearch = new Search(argv[2]);
    	SearchObjects.push_back(newSearch);
          }
    
        for(int h=1;h<cuts.size()-1;h++)
          {
    	vector<int> check;
    
    	Search *newSearch = new Search(argv[2]);
    
    	newSearch->find(&text[0],cuts[h]-(strlen(argv[2])-1),cuts[h]+(strlen(argv[2])-1));
    	check = newSearch->get_hits();
    	if(!check.empty()){
    		cuts[h]=check[0];}
    
          }
    
     double start = omp_get_wtime();
    
    #pragma omp parallel num_threads(nmbr_of_threads) shared(SearchObjects,text,cuts)
    {
    #pragma omp for schedule(static,1) nowait
    	for(int h=0;h<nmbr_of_threads;h++)
          { 
    		SearchObjects[h]->find(&text[0],cuts[h],cuts[h+1]);
          }
    }
    
        double end = omp_get_wtime();
        vector<int>all_hits;
        int all_counts = 0;
        for(int h=0;h<nmbr_of_threads;h++)
          {
    	vector<int>hits=SearchObjects[h]->get_hits();
    	for(int hi=0;hi<hits.size();hi++)
    	  all_hits.push_back(hits[hi]);
    	all_counts+=SearchObjects[h]->get_count();
          }
           cout<<"\nHorspool:\t"<<all_counts<<" hits found in "<<(int)((end-start)*1000)<<"ms"<<endl;
    
    if (!createFile(all_hits, argv[4]))
        {
            cerr << "Could not open output file." << endl;
            return 1;
        }
     return 0;
    }
    

    MfG Monchichu



  • Lies dir mal bitte den Link in meiner Signatur durch - vor allem den Teil mit "aufs Wesentliche reduzieren". Zu deinem Problem: sagt der Compiler beim Übersetzen was zum #pragma omp? Musst du ggf. noch irgendeinen Parameter beim compilieren mitgeben? Das ist sehr compilerspezifisch, da OMP kein Standard-C++ ist.



  • Ich kompiliere auf einem Linux mit dem Befehl g++ -Wall -fopenmp xxx.cpp -o xxx und Fehler bekomme ich keine nur unsigned int warnings welche jedoch vernachlässigt werden können.


  • Mod

    Funktioniert ganz hervorragend bei mir:

    [b]$>[/b] g++ test.cc -Wall -Wextra -O3
    test.cc: In function ‘bool createFile(std::vector<int, std::allocator<int> >&, char*)’:
    test.cc:120: warning: comparison between signed and unsigned integer expressions
    test.cc: In function ‘int main(int, char**)’:
    test.cc:159: warning: comparison between signed and unsigned integer expressions
    test.cc:189: warning: comparison between signed and unsigned integer expressions
    [b]$>[/b] dd if=/dev/urandom of=test.dat bs=10000 count=10000
    10000+0 records in
    10000+0 records out
    100000000 bytes (100 MB) copied, 12.7066 s, 7.9 MB/s
    [b]$>[/b] ./a.out  test.dat test 1 test.result
    Horspool:	0 hits found in 1273ms
    [b]$>[/b] ./a.out  test.dat test 2 test.result
    Horspool:	0 hits found in 664ms
    [b]$>[/b] ./a.out  test.dat test 3 test.result
    Horspool:	0 hits found in 443ms
    [b]$>[/b] ./a.out  test.dat test 4 test.result
    Horspool:	0 hits found in 332ms
    

    Einziger Unterschied der mir auffällt zu deinem Versuch ist, dass ich getreu dem Motto "niemanden interessiert es, wie schnell dein unoptimierter Code läuft" gehandelt habe.


  • Mod

    Das "ganz hervorragend" sollte man noch einschränken: Dein Programm ist ein einziges großes Speicherloch. Warum nutzt du soviel new und Pointergefrickel, wenn du es noch nicht einmal kannst und wenn man es in C++ sowieso nicht braucht und wenn doch, dann ganz anders?


Anmelden zum Antworten