diff --git a/CMakeLists.txt b/CMakeLists.txt index af5f97e..7ace84d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,6 +6,6 @@ cmake_minimum_required (VERSION 3.8) project ("ParallelSearch") # Fügen Sie der ausführbaren Datei dieses Projekts eine Quelle hinzu. -add_executable (ParallelSearch "main.cpp" "SearchJob.hpp" "TestRunner.hpp") +add_executable (ParallelSearch "main.cpp" "SearchJob.hpp" "TestRunner.hpp" "ParallelSearch.hpp") # TODO: Fügen Sie bei Bedarf Tests hinzu, und installieren Sie Ziele. diff --git a/CMakeSettings.json b/CMakeSettings.json index 9204f06..0c5fbf9 100644 --- a/CMakeSettings.json +++ b/CMakeSettings.json @@ -10,6 +10,18 @@ "cmakeCommandArgs": "", "buildCommandArgs": "", "ctestCommandArgs": "" + }, + { + "name": "x64-Release", + "generator": "Ninja", + "configurationType": "RelWithDebInfo", + "buildRoot": "${projectDir}\\out\\build\\${name}", + "installRoot": "${projectDir}\\out\\install\\${name}", + "cmakeCommandArgs": "", + "buildCommandArgs": "", + "ctestCommandArgs": "", + "inheritEnvironments": [ "msvc_x64_x64" ], + "variables": [] } ] } \ No newline at end of file diff --git a/ParallelSearch.hpp b/ParallelSearch.hpp new file mode 100644 index 0000000..8485485 --- /dev/null +++ b/ParallelSearch.hpp @@ -0,0 +1,43 @@ +#ifndef PARALLELSEARCH_HPP +#define PARALLELSEARCH_HPP + +#include +#include +#include "SearchJob.hpp" + +template +class ParallelSearch +{ +public: + // Type of the search result + typedef std::vector ResultList; + // underlying search jobs + typedef std::vector> JobList; + + // Create partial search job for provided range + SearchJob(unsigned workerCount, Iterator begin, Iterator end, const std::string& pattern) + { + + } + + // Destructor + ~SearchJob() + { + } + + // run the search job and collect results internally + void run() + { + + } + + // return the result + const ResultList& GetResult() const { return result_; }; + +private: + // jobs to execute + JobList jobList_; + // result of the search + ResultList result_; +}; +#endif \ No newline at end of file diff --git a/SearchJob.hpp b/SearchJob.hpp index 409c006..ac87795 100644 --- a/SearchJob.hpp +++ b/SearchJob.hpp @@ -31,7 +31,7 @@ public: 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); } diff --git a/main.cpp b/main.cpp index dba0dc0..1e4064c 100644 --- a/main.cpp +++ b/main.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include "SearchJob.hpp" #include "TestRunner.hpp" @@ -13,6 +14,9 @@ typedef std::vector WordList; typedef SearchJob WordSearchJob; +typedef std::vector SearchJobList; + + void create_testdata(WordList& words) { const char start = 'A'; @@ -24,6 +28,7 @@ void create_testdata(WordList& words) for (str[2] = start; str[2] <= end; str[2]++) for (str[3] = start; str[3] <= end; str[3]++) words.push_back(std::string(str, 4)); + } void shuffle_testdata(WordList& words) @@ -37,26 +42,83 @@ void run_wordsearch(WordSearchJob& job) job.run(); } +void run_parallel_wordsearch(std::vector& jobList) +{ + std::vector threads; + + for (WordSearchJob& job : jobList) + { + threads.push_back(std::thread(&WordSearchJob::run, &job)); + } + + for (std::thread& th : threads) + { + th.join(); + } +} int main() { double time_span; + std::string pattern = "ABC"; + WordList test_data; std::cout << "Hello World." << std::endl; - + time_span = TestRunner(create_testdata, test_data); std::cout << "It took me " << time_span << " seconds to create " << test_data.size() << " words." << std::endl; time_span = TestRunner(shuffle_testdata, test_data); std::cout << "It took me " << time_span << " seconds to shuffle " << test_data.size() << " words." << std::endl; - SearchJob job(test_data.begin(), test_data.end(), "ABC"); + SearchJob job(test_data.begin(), test_data.end(), pattern); time_span = TestRunner(run_wordsearch, job); std::cout << "It took me " << time_span << " seconds to find " << job.GetResult().size() << " matches." << std::endl; + std::vector jobList; + + unsigned coreCount = std::thread::hardware_concurrency(); + std::size_t bucketSize = test_data.size() / coreCount; + std::size_t remains = test_data.size() % coreCount; + + std::cout << "Creating " << coreCount << " search jobs, bucketSize = " << bucketSize << std::endl; + + std::size_t offset = 0; + while(offset < test_data.size()) + { + // compute [first; last( iterators for sub-range + std::size_t size = bucketSize + remains; + WordList::const_iterator first = test_data.begin() + offset; + WordList::const_iterator last = first + bucketSize + remains; + + std::cout << "offset = " << offset << " size = " << size << std::endl; + + // add appropriate search job + jobList.push_back(WordSearchJob(first, last, pattern)); + + // increment offset + offset += size; + // clear remains (it has been added to first bucket) + remains = 0; + } + + + + time_span = TestRunner(run_parallel_wordsearch, jobList); + + // collect search results ... + unsigned found = 0; + for (WordSearchJob& job : jobList) + { + found += job.GetResult().size(); + } + std::cout << "It took me " << time_span << " seconds to find " << found << " matches." << std::endl; + + + std::cout << std::endl; return 0;