|
10 | 10 | #include <cassert>
|
11 | 11 | #include <cstdlib>
|
12 | 12 | #include <sstream>
|
| 13 | +#include <regex> |
| 14 | +#include <iterator> |
13 | 15 | #ifdef _MSC_VER
|
14 | 16 | #include <intrin.h>
|
15 | 17 | #endif
|
@@ -75,40 +77,47 @@ bool LLModel::Implementation::isImplementation(const Dlhandle &dl) {
|
75 | 77 | return dl.get<bool(uint32_t)>("is_g4a_backend_model_implementation");
|
76 | 78 | }
|
77 | 79 |
|
| 80 | +static bool s_scanned = false; |
| 81 | + |
78 | 82 | const std::vector<LLModel::Implementation> &LLModel::Implementation::implementationList() {
|
79 |
| - // NOTE: allocated on heap so we leak intentionally on exit so we have a chance to clean up the |
80 |
| - // individual models without the cleanup of the static list interfering |
81 |
| - static auto* libs = new std::vector<Implementation>([] () { |
82 |
| - std::vector<Implementation> fres; |
83 |
| - |
84 |
| - auto search_in_directory = [&](const std::string& paths) { |
85 |
| - std::stringstream ss(paths); |
86 |
| - std::string path; |
87 |
| - // Split the paths string by the delimiter and process each path. |
88 |
| - while (std::getline(ss, path, ';')) { |
89 |
| - std::filesystem::path fs_path(path); |
90 |
| - // Iterate over all libraries |
91 |
| - for (const auto& f : std::filesystem::directory_iterator(fs_path)) { |
92 |
| - const std::filesystem::path& p = f.path(); |
93 |
| - if (p.extension() != LIB_FILE_EXT) continue; |
94 |
| - // Add to list if model implementation |
95 |
| - try { |
96 |
| - Dlhandle dl(p.string()); |
97 |
| - if (!Implementation::isImplementation(dl)) { |
98 |
| - continue; |
99 |
| - } |
100 |
| - fres.emplace_back(Implementation(std::move(dl))); |
101 |
| - } catch (...) {} |
102 |
| - } |
| 83 | + static std::vector<LLModel::Implementation> s_impl_libs; |
| 84 | + |
| 85 | + if(s_scanned) { return s_impl_libs; } |
| 86 | + std::string impl_name_re = "(bert|llama|gptj|llamamodel-mainline)"; |
| 87 | + if (requires_avxonly()) { |
| 88 | + impl_name_re += "-avxonly"; |
| 89 | + } else { |
| 90 | + impl_name_re += "-(default|metal)"; |
| 91 | + } |
| 92 | + std::regex re(impl_name_re); |
| 93 | + auto search_in_directory = [&](const std::string& paths) { |
| 94 | + std::stringstream ss(paths); |
| 95 | + std::string path; |
| 96 | + // Split the paths string by the delimiter and process each path. |
| 97 | + while (std::getline(ss, path, ';')) { |
| 98 | + std::filesystem::path fs_path(path); |
| 99 | + // Iterate over all libraries |
| 100 | + for (const auto& f : std::filesystem::directory_iterator(fs_path)) { |
| 101 | + const std::filesystem::path& p = f.path(); |
| 102 | + |
| 103 | + if (p.extension() != LIB_FILE_EXT) continue; |
| 104 | + if (!std::regex_search(p.stem().string(), re)) continue; |
| 105 | + |
| 106 | + // Add to list if model implementation |
| 107 | + try { |
| 108 | + Dlhandle dl(p.string()); |
| 109 | + if (!Implementation::isImplementation(dl)) { |
| 110 | + continue; |
| 111 | + } |
| 112 | + s_impl_libs.emplace_back(Implementation(std::move(dl))); |
| 113 | + } catch (...) {} |
103 | 114 | }
|
104 |
| - }; |
105 |
| - |
106 |
| - search_in_directory(s_implementations_search_path); |
| 115 | + } |
| 116 | + }; |
| 117 | + search_in_directory(s_implementations_search_path); |
| 118 | + s_scanned = true; |
107 | 119 |
|
108 |
| - return fres; |
109 |
| - }()); |
110 |
| - // Return static result |
111 |
| - return *libs; |
| 120 | + return s_impl_libs; |
112 | 121 | }
|
113 | 122 |
|
114 | 123 | const LLModel::Implementation* LLModel::Implementation::implementation(const char *fname, const std::string& buildVariant) {
|
@@ -170,6 +179,7 @@ LLModel *LLModel::Implementation::construct(const std::string &modelPath, std::s
|
170 | 179 |
|
171 | 180 | void LLModel::Implementation::setImplementationsSearchPath(const std::string& path) {
|
172 | 181 | s_implementations_search_path = path;
|
| 182 | + s_scanned = false; |
173 | 183 | }
|
174 | 184 |
|
175 | 185 | const std::string& LLModel::Implementation::implementationsSearchPath() {
|
|
0 commit comments