remove templating ... it is not required
This commit is contained in:
parent
b9072abf13
commit
670ce5b0b3
@ -6,6 +6,6 @@ cmake_minimum_required (VERSION 3.8)
|
|||||||
project ("ParallelSearch")
|
project ("ParallelSearch")
|
||||||
|
|
||||||
# Fügen Sie der ausführbaren Datei dieses Projekts eine Quelle hinzu.
|
# Fügen Sie der ausführbaren Datei dieses Projekts eine Quelle hinzu.
|
||||||
add_executable (ParallelSearch "main.cpp" "TestRunner.hpp" "ParallelSearch.hpp" "Parameters.hpp")
|
add_executable (ParallelSearch "main.cpp" "TestRunner.hpp" "ParallelSearch.hpp" "Parameters.hpp" "WordList.hpp" "ParallelSearch.cpp")
|
||||||
|
|
||||||
# TODO: Fügen Sie bei Bedarf Tests hinzu, und installieren Sie Ziele.
|
# TODO: Fügen Sie bei Bedarf Tests hinzu, und installieren Sie Ziele.
|
||||||
|
|||||||
66
ParallelSearch.cpp
Normal file
66
ParallelSearch.cpp
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
#include "ParallelSearch.hpp"
|
||||||
|
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
ParallelSearch::SearchJob::SearchJob(Iterator begin, Iterator end, const std::string& pattern) : begin_(begin), end_(end), pattern_(pattern)
|
||||||
|
{
|
||||||
|
result_.reserve(INITIAL_RESERVE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ParallelSearch::SearchJob::execute()
|
||||||
|
{
|
||||||
|
for (Iterator itr = begin_; itr != end_; itr++)
|
||||||
|
{
|
||||||
|
if (0 == itr->compare(0, pattern_.size(), pattern_))
|
||||||
|
{
|
||||||
|
// found a match, save the index
|
||||||
|
result_.push_back(itr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ParallelSearch::ParallelSearch(unsigned workerCount, Iterator begin, Iterator end, const std::string& pattern)
|
||||||
|
{
|
||||||
|
std::size_t totalCount = end - begin;
|
||||||
|
std::size_t bucketSize = totalCount / workerCount;
|
||||||
|
std::size_t remains = totalCount % workerCount;
|
||||||
|
|
||||||
|
std::size_t offset = 0;
|
||||||
|
while (offset < totalCount)
|
||||||
|
{
|
||||||
|
// compute [first; last( iterators for sub-range
|
||||||
|
std::size_t size = bucketSize + remains;
|
||||||
|
Iterator first = begin + offset;
|
||||||
|
Iterator last = begin + offset + size;
|
||||||
|
|
||||||
|
// add appropriate search job
|
||||||
|
jobList_.push_back(SearchJob(first, last, pattern));
|
||||||
|
|
||||||
|
// increment offset
|
||||||
|
offset += size;
|
||||||
|
// clear remains (it has been added to first bucket)
|
||||||
|
remains = 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void ParallelSearch::run()
|
||||||
|
{
|
||||||
|
// start thread for each job
|
||||||
|
std::vector<std::thread> threads;
|
||||||
|
for (SearchJob& job : jobList_)
|
||||||
|
{
|
||||||
|
threads.push_back(std::thread(&SearchJob::execute, &job));
|
||||||
|
}
|
||||||
|
|
||||||
|
// wait for all threads to join
|
||||||
|
for (std::thread& th : threads)
|
||||||
|
{
|
||||||
|
th.join();
|
||||||
|
}
|
||||||
|
|
||||||
|
// collect the results
|
||||||
|
for (SearchJob& job : jobList_)
|
||||||
|
{
|
||||||
|
result_.insert(result_.end(), job.get_result().begin(), job.get_result().end());
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,16 +1,14 @@
|
|||||||
#ifndef PARALLELSEARCH_HPP
|
#ifndef PARALLELSEARCH_HPP
|
||||||
#define PARALLELSEARCH_HPP
|
#define PARALLELSEARCH_HPP
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <iostream>
|
#include "WordList.hpp"
|
||||||
#include <thread>
|
|
||||||
|
|
||||||
template <typename Iterator>
|
|
||||||
class ParallelSearch
|
class ParallelSearch
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
// Iterator type used inside the class
|
||||||
|
typedef WordList::const_iterator Iterator;
|
||||||
// Type of the search result
|
// Type of the search result
|
||||||
typedef std::vector<Iterator> ResultList;
|
typedef std::vector<Iterator> ResultList;
|
||||||
|
|
||||||
@ -61,71 +59,4 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
template <typename Iterator>
|
|
||||||
ParallelSearch<Iterator>::SearchJob::SearchJob(Iterator begin, Iterator end, const std::string& pattern) : begin_(begin), end_(end), pattern_(pattern)
|
|
||||||
{
|
|
||||||
result_.reserve(INITIAL_RESERVE);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Iterator>
|
|
||||||
void ParallelSearch<Iterator>::SearchJob::execute()
|
|
||||||
{
|
|
||||||
for (Iterator itr = begin_; itr != end_; itr++)
|
|
||||||
{
|
|
||||||
if (0 == itr->compare(0, pattern_.size(), pattern_))
|
|
||||||
{
|
|
||||||
// found a match, save the index
|
|
||||||
result_.push_back(itr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Iterator>
|
|
||||||
ParallelSearch<Iterator>::ParallelSearch(unsigned workerCount, Iterator begin, Iterator end, const std::string& pattern)
|
|
||||||
{
|
|
||||||
std::size_t totalCount = end - begin;
|
|
||||||
std::size_t bucketSize = totalCount / workerCount;
|
|
||||||
std::size_t remains = totalCount % workerCount;
|
|
||||||
|
|
||||||
std::size_t offset = 0;
|
|
||||||
while (offset < totalCount)
|
|
||||||
{
|
|
||||||
// compute [first; last( iterators for sub-range
|
|
||||||
std::size_t size = bucketSize + remains;
|
|
||||||
Iterator first = begin + offset;
|
|
||||||
Iterator last = begin + offset + size;
|
|
||||||
|
|
||||||
// add appropriate search job
|
|
||||||
jobList_.push_back(SearchJob(first, last, pattern));
|
|
||||||
|
|
||||||
// increment offset
|
|
||||||
offset += size;
|
|
||||||
// clear remains (it has been added to first bucket)
|
|
||||||
remains = 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Iterator>
|
|
||||||
void ParallelSearch<Iterator>::run()
|
|
||||||
{
|
|
||||||
// start thread for each job
|
|
||||||
std::vector<std::thread> threads;
|
|
||||||
for (SearchJob& job : jobList_)
|
|
||||||
{
|
|
||||||
threads.push_back(std::thread(&SearchJob::execute, &job));
|
|
||||||
}
|
|
||||||
|
|
||||||
// wait for all threads to join
|
|
||||||
for (std::thread& th : threads)
|
|
||||||
{
|
|
||||||
th.join();
|
|
||||||
}
|
|
||||||
|
|
||||||
// collect the results
|
|
||||||
for (SearchJob& job : jobList_)
|
|
||||||
{
|
|
||||||
result_.insert(result_.end(), job.get_result().begin(), job.get_result().end());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
11
WordList.hpp
Normal file
11
WordList.hpp
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#ifndef WORDLIST_HPP
|
||||||
|
#define WORDLIST_HPP
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
// Type of our hay stack: a list of strings
|
||||||
|
typedef std::vector<std::string> WordList;
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
54
main.cpp
54
main.cpp
@ -8,11 +8,6 @@
|
|||||||
#include "TestRunner.hpp"
|
#include "TestRunner.hpp"
|
||||||
#include "Parameters.hpp"
|
#include "Parameters.hpp"
|
||||||
|
|
||||||
// Type of our hay stack: a list of strings
|
|
||||||
typedef std::vector<std::string> WordList;
|
|
||||||
|
|
||||||
typedef ParallelSearch<WordList::const_iterator> ParallelWordSearch;
|
|
||||||
|
|
||||||
void create_testdata(WordList& words)
|
void create_testdata(WordList& words)
|
||||||
{
|
{
|
||||||
const char start = 'A';
|
const char start = 'A';
|
||||||
@ -35,27 +30,23 @@ void shuffle_testdata(WordList& words)
|
|||||||
std::shuffle(words.begin(), words.end(), rng);
|
std::shuffle(words.begin(), words.end(), rng);
|
||||||
}
|
}
|
||||||
|
|
||||||
void run_wordsearch(ParallelWordSearch& search)
|
void run_wordsearch(ParallelSearch& search)
|
||||||
{
|
{
|
||||||
search.run();
|
search.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool check_result(const WordList& haystack, const std::string& pattern, const ParallelWordSearch::ResultList& result)
|
bool check_result(const WordList& haystack, const std::string& pattern, const ParallelSearch::ResultList& result)
|
||||||
{
|
{
|
||||||
bool result_is_valid = true;
|
bool result_valid = true;
|
||||||
|
|
||||||
// check number of matches
|
// check number of matches
|
||||||
const unsigned TESTPATTERN_LENGTH = 4;
|
const unsigned TESTPATTERN_LENGTH = 4;
|
||||||
unsigned expected_count = static_cast<unsigned>(pow(26.0, double(TESTPATTERN_LENGTH - pattern.size())));
|
unsigned expected_count = static_cast<unsigned>(pow(26.0, double(TESTPATTERN_LENGTH - pattern.size())));
|
||||||
std::cout << "number of matches expected: " << expected_count << " got: " << result.size() << " --> ";
|
|
||||||
if (result.size() == expected_count)
|
if (result.size() != expected_count)
|
||||||
{
|
{
|
||||||
std::cout << "OK" << std::endl;
|
std::cout << "wrong number of matches: expected " << expected_count << " but got " << result.size() << std::endl;
|
||||||
}
|
result_valid = false;
|
||||||
else
|
|
||||||
{
|
|
||||||
std::cout << "ERROR" << std::endl;
|
|
||||||
result_is_valid = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// verify matches contain the search-pattern
|
// verify matches contain the search-pattern
|
||||||
@ -68,12 +59,12 @@ bool check_result(const WordList& haystack, const std::string& pattern, const Pa
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::cout << "found mismatch: " << *itr << std::endl;
|
std::cout << "found unexpected entry in result: " << *itr << std::endl;
|
||||||
result_is_valid = false;
|
result_valid = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "verified " << valid_count << " matches --> " << ((result.size() == valid_count) ? "OK" : "ERROR") << std::endl;
|
std::cout << "result is " << (result_valid ? "VALID" : "INVALID") << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
@ -90,9 +81,10 @@ int main(int argc, char** argv)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "Workercount: " << parameters.WorkerCount() << std::endl;
|
std::cout
|
||||||
std::cout << "Search pattern: " << parameters.SearchPattern() << std::endl;
|
<< "Workercount: " << parameters.WorkerCount() << std::endl
|
||||||
std::cout << std::endl;
|
<< "Search pattern: " << parameters.SearchPattern() << std::endl
|
||||||
|
<< std::endl;
|
||||||
|
|
||||||
time_span = TestRunner(create_testdata, test_data);
|
time_span = TestRunner(create_testdata, test_data);
|
||||||
std::cout << "created test_data (" << test_data.size() << " words) in " << time_span << " seconds" << std::endl;
|
std::cout << "created test_data (" << test_data.size() << " words) in " << time_span << " seconds" << std::endl;
|
||||||
@ -100,21 +92,17 @@ int main(int argc, char** argv)
|
|||||||
time_span = TestRunner(shuffle_testdata, test_data);
|
time_span = TestRunner(shuffle_testdata, test_data);
|
||||||
std::cout << "shuffled test_data in " << time_span << " seconds" << std::endl;
|
std::cout << "shuffled test_data in " << time_span << " seconds" << std::endl;
|
||||||
|
|
||||||
ParallelWordSearch wordSearch(1, test_data.begin(), test_data.end(), parameters.SearchPattern());
|
ParallelSearch linearSearch(1, test_data.begin(), test_data.end(), parameters.SearchPattern());
|
||||||
|
time_span = TestRunner(run_wordsearch, linearSearch);
|
||||||
time_span = TestRunner(run_wordsearch, wordSearch);
|
std::cout << "linear search found " << linearSearch.get_result().size() << " matches in " << time_span << " seconds" << std::endl;
|
||||||
std::cout << "linear search found " << wordSearch.get_result().size() << " matches in " << time_span << " seconds" << std::endl;
|
|
||||||
|
|
||||||
ParallelWordSearch parallelWordSearch(parameters.WorkerCount(), test_data.begin(), test_data.end(), parameters.SearchPattern());
|
ParallelSearch parallelSearch(parameters.WorkerCount(), test_data.begin(), test_data.end(), parameters.SearchPattern());
|
||||||
time_span = TestRunner(run_wordsearch, parallelWordSearch);
|
time_span = TestRunner(run_wordsearch, parallelSearch);
|
||||||
std::cout << "parallel search found " << parallelWordSearch.get_result().size() << " matches in " << time_span << " seconds" << std::endl;
|
std::cout << "parallel search found " << parallelSearch.get_result().size() << " matches in " << time_span << " seconds" << std::endl;
|
||||||
|
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
std::cout << "checking result of parallel search ..." << std::endl;
|
std::cout << "checking result of parallel search ..." << std::endl;
|
||||||
bool result_valid = check_result(test_data, parameters.SearchPattern(), parallelWordSearch.get_result());
|
check_result(test_data, parameters.SearchPattern(), parallelSearch.get_result());
|
||||||
|
|
||||||
std::cout << std::endl << "Result is " << (result_valid ? "VALID" : "INVALID") << std::endl;
|
|
||||||
std::cout << std::endl;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user