diff --git a/lib_vector_search/include/grouped_finder.h b/lib_vector_search/include/grouped_finder.h index 572395a..b562330 100644 --- a/lib_vector_search/include/grouped_finder.h +++ b/lib_vector_search/include/grouped_finder.h @@ -4,14 +4,15 @@ #include "word_list.h" #include +#include class GroupedFinder : public Finder { private: - std::map groups_; + std::map> groups_; public: GroupedFinder(const WordList &word_list); virtual std::forward_list - find_prefix(std::string_view search_prefix) const override; + find_prefix(std::string_view search_term) const override; }; diff --git a/lib_vector_search/include/parallel_finder.h b/lib_vector_search/include/parallel_finder.h index 543096b..55c776b 100644 --- a/lib_vector_search/include/parallel_finder.h +++ b/lib_vector_search/include/parallel_finder.h @@ -11,5 +11,5 @@ public: ParallelFinder(const WordList &word_list); std::forward_list - find_prefix(std::string_view search_prefix) const override; + find_prefix(std::string_view search_term) const override; }; diff --git a/lib_vector_search/include/sorted_linear_finder.h b/lib_vector_search/include/sorted_linear_finder.h index b2437d0..866c2b2 100644 --- a/lib_vector_search/include/sorted_linear_finder.h +++ b/lib_vector_search/include/sorted_linear_finder.h @@ -3,9 +3,11 @@ #include "finder.h" #include "word_list.h" +#include + class SortedLinearFinder : public Finder { private: - WordRefList word_list_; + std::vector word_list_; public: SortedLinearFinder(const WordList &word_list); diff --git a/lib_vector_search/include/word_list.h b/lib_vector_search/include/word_list.h index 3c0b5d9..ca52d9a 100644 --- a/lib_vector_search/include/word_list.h +++ b/lib_vector_search/include/word_list.h @@ -1,8 +1,6 @@ #pragma once #include -#include -#include #include #include @@ -13,19 +11,4 @@ public: static WordList fourCaps(); static WordList fromFile(const std::filesystem::path &path); - - static void find_prefix_in_range( - const WordList &word_list, const std::string_view &search_prefix, - size_t start_index, size_t end_index, - std::forward_list &result, std::mutex &result_mutex); -}; - -class WordRefList : public std::vector { -public: - WordRefList(const WordList &source); - - static void find_prefix_in_range( - const WordRefList &word_list, const std::string_view &search_prefix, - size_t start_index, size_t end_index, - std::forward_list &result, std::mutex &result_mutex); }; diff --git a/lib_vector_search/src/grouped_finder.cpp b/lib_vector_search/src/grouped_finder.cpp index bb8ee88..39b8b43 100644 --- a/lib_vector_search/src/grouped_finder.cpp +++ b/lib_vector_search/src/grouped_finder.cpp @@ -5,8 +5,8 @@ #include #include -using std::mutex, std::vector, std::thread, std::string, std::forward_list, - std::string_view; +using std::mutex, std::vector, std::thread, std::lock_guard, std::string, + std::forward_list, std::string_view; GroupedFinder::GroupedFinder(const WordList &word_list) { for (const auto &word : word_list) { @@ -14,9 +14,9 @@ GroupedFinder::GroupedFinder(const WordList &word_list) { } } -forward_list -GroupedFinder::find_prefix(string_view search_prefix) const { - const auto group = groups_.find(search_prefix.front()); +std::forward_list +GroupedFinder::find_prefix(std::string_view search_term) const { + const auto group = groups_.find(search_term.front()); if (group == groups_.cend()) { return {}; } @@ -27,26 +27,41 @@ GroupedFinder::find_prefix(string_view search_prefix) const { const auto thread_count = std::min(std::thread::hardware_concurrency(), word_list_size); - forward_list result; - mutex result_mutex; + forward_list matching_words; + mutex matching_words_mutex; vector search_threads; for (size_t thread_index = 0; thread_index < thread_count; ++thread_index) { - const size_t first_index = thread_index * (word_list_size / thread_count); - - const size_t last_index = + const size_t first_word_index = + thread_index * (word_list_size / thread_count); + const size_t last_word_index = (thread_index == thread_count - 1) ? word_list_size : (thread_index + 1) * (word_list_size / thread_count); search_threads.emplace_back( - WordRefList::find_prefix_in_range, cref(word_list), cref(search_prefix), - first_index, last_index, ref(result), ref(result_mutex)); + [](const vector &word_list, + const string_view &search_term, forward_list &result, + size_t start_index, size_t end_index, mutex &result_mutex) { + forward_list thread_results; + for (size_t index = start_index; index < end_index; ++index) { + const auto ¤t_word = word_list[index]; + if (current_word->starts_with(search_term)) { + thread_results.push_front(current_word); + } + } + if (!thread_results.empty()) { + const lock_guard lock(result_mutex); + result.merge(thread_results); + } + }, + cref(word_list), cref(search_term), ref(matching_words), + first_word_index, last_word_index, ref(matching_words_mutex)); } for (auto &thread : search_threads) { thread.join(); } - return result; + return matching_words; } diff --git a/lib_vector_search/src/parallel_finder.cpp b/lib_vector_search/src/parallel_finder.cpp index 15c6a06..1b7effe 100644 --- a/lib_vector_search/src/parallel_finder.cpp +++ b/lib_vector_search/src/parallel_finder.cpp @@ -3,36 +3,51 @@ #include #include -using std::mutex, std::thread, std::vector, std::forward_list, std::string, - std::string_view; +using std::mutex, std::thread, std::lock_guard, std::vector, std::forward_list, + std::string, std::string_view; ParallelFinder::ParallelFinder(const WordList &word_list) : word_list_(word_list) {} forward_list -ParallelFinder::find_prefix(string_view search_prefix) const { +ParallelFinder::find_prefix(string_view search_term) const { forward_list result; mutex result_mutex; - const size_t word_list_size = word_list_.size(); - const size_t thread_count = - std::min(thread::hardware_concurrency(), word_list_size); + const auto word_list_size = word_list_.size(); - vector search_threads; + const size_t thread_count = thread::hardware_concurrency(); + + vector threads; for (size_t thread_index = 0; thread_index < thread_count; ++thread_index) { - const size_t first_index = thread_index * (word_list_size / thread_count); - - const size_t last_index = + const size_t first_word_index = + thread_index * (word_list_size / thread_count); + const size_t last_word_index = (thread_index == thread_count - 1) ? word_list_size : (thread_index + 1) * (word_list_size / thread_count); - search_threads.emplace_back( - WordList::find_prefix_in_range, cref(word_list_), cref(search_prefix), - first_index, last_index, ref(result), ref(result_mutex)); + threads.emplace_back( + [](const WordList &word_list, const string_view &search_term, + forward_list &result, size_t start_index, + size_t end_index, mutex &result_mutex) { + forward_list thread_results; + for (size_t index = start_index; index < end_index; ++index) { + const auto ¤t_word = word_list[index]; + if (current_word.starts_with(search_term)) { + thread_results.push_front(¤t_word); + } + } + if (!thread_results.empty()) { + const lock_guard lock(result_mutex); + result.merge(thread_results); + } + }, + cref(word_list_), cref(search_term), ref(result), first_word_index, + last_word_index, ref(result_mutex)); } - for (auto &thread : search_threads) { + for (auto &thread : threads) { thread.join(); } diff --git a/lib_vector_search/src/sorted_linear_finder.cpp b/lib_vector_search/src/sorted_linear_finder.cpp index 3648bb2..db11154 100644 --- a/lib_vector_search/src/sorted_linear_finder.cpp +++ b/lib_vector_search/src/sorted_linear_finder.cpp @@ -1,16 +1,19 @@ #include "sorted_linear_finder.h" #include +#include using std::forward_list, std::string, std::string_view; -SortedLinearFinder::SortedLinearFinder(const WordList &word_list) - : word_list_(word_list) { +SortedLinearFinder::SortedLinearFinder(const WordList &word_list) { + std::transform(word_list.cbegin(), word_list.cend(), + std::back_inserter(word_list_), + [](const string &word) { return &word; }); + std::sort( word_list_.begin(), word_list_.end(), [](const string *left, const string *right) { return *left < *right; }); } - forward_list SortedLinearFinder::find_prefix(string_view search_term) const { forward_list matching_words; diff --git a/lib_vector_search/src/word_list.cpp b/lib_vector_search/src/word_list.cpp index e810451..db01a19 100644 --- a/lib_vector_search/src/word_list.cpp +++ b/lib_vector_search/src/word_list.cpp @@ -57,47 +57,3 @@ WordList WordList::fromFile(const std::filesystem::path &path) { return word_list; } - -void WordList::find_prefix_in_range( - const WordList &word_list, const std::string_view &search_prefix, - size_t start_index, size_t end_index, - std::forward_list &result, std::mutex &result_mutex) { - std::forward_list local_results; - - for (size_t index = start_index; index < end_index; ++index) { - const auto ¤t_word = word_list[index]; - if (current_word.starts_with(search_prefix)) { - local_results.push_front(¤t_word); - } - } - - if (!local_results.empty()) { - const std::lock_guard lock(result_mutex); - result.merge(local_results); - } -}; - -WordRefList::WordRefList(const WordList &source) { - for (const auto &word : source) { - push_back(&word); - } -} - -void WordRefList::find_prefix_in_range( - const WordRefList &word_list, const std::string_view &search_prefix, - size_t start_index, size_t end_index, - std::forward_list &result, std::mutex &result_mutex) { - std::forward_list local_results; - - for (size_t index = start_index; index < end_index; ++index) { - const auto *current_word = word_list[index]; - if (current_word->starts_with(search_prefix)) { - local_results.push_front(current_word); - } - } - - if (!local_results.empty()) { - const std::lock_guard lock(result_mutex); - result.merge(local_results); - } -}; diff --git a/vector_search_cli/main.cpp b/vector_search_cli/main.cpp index 117b81f..9922090 100644 --- a/vector_search_cli/main.cpp +++ b/vector_search_cli/main.cpp @@ -30,8 +30,9 @@ void test_finder_search(Finder &finder, string_view name, auto result = finder.find_prefix(search_term); find_timer.stop(); - cout << name << "(" << search_term << ") took " << find_timer << " for " - << std::distance(result.cbegin(), result.cend()) << " results" << endl; + cout << name << "(" << search_term << ") took " << find_timer << endl; + cout << "result list is " << std::distance(result.cbegin(), result.cend()) + << " element(s) long" << endl; } template @@ -43,8 +44,7 @@ void test_finder(const WordList &word_list, string_view finder_name) { constructor_timer.stop(); cout << finder_name << " constructor took " << constructor_timer << endl; - for (const auto &search_term : - {"A", "Z", "AB", "ZY", "ABC", "ZYX", "ABCD", "ZYXW"}) { + for (const auto &search_term : {"A", "AB", "ABC", "ABCD"}) { test_finder_search(finder, finder_name, search_term); } }