11#include " ggml-backend-impl.h"
22#include " ggml-backend.h"
33#include " ggml-impl.h"
4+ #include < algorithm>
45#include < cstring>
56#include < vector>
67
4546#include " ggml-kompute.h"
4647#endif
4748
49+ struct ggml_backend_reg_entry {
50+ ggml_backend_reg_t reg;
51+ void * handle;
52+ };
53+
4854struct ggml_backend_registry {
49- std::vector<ggml_backend_reg_t > backends;
55+ std::vector<ggml_backend_reg_entry > backends;
5056 std::vector<ggml_backend_dev_t > devices;
5157
5258 ggml_backend_registry () {
@@ -82,7 +88,13 @@ struct ggml_backend_registry {
8288#endif
8389 }
8490
85- void register_backend (ggml_backend_reg_t reg) {
91+ ~ggml_backend_registry () {
92+ while (!backends.empty ()) {
93+ ggml_backend_unload (backends.back ().reg );
94+ }
95+ }
96+
97+ void register_backend (ggml_backend_reg_t reg, void * handle = nullptr ) {
8698 if (!reg) {
8799 return ;
88100 }
@@ -91,7 +103,7 @@ struct ggml_backend_registry {
91103 GGML_LOG_DEBUG (" %s: registered backend %s (%zu devices)\n " ,
92104 __func__, ggml_backend_reg_name (reg), ggml_backend_reg_dev_count (reg));
93105#endif
94- backends.push_back (reg);
106+ backends.push_back ({ reg, handle } );
95107 for (size_t i = 0 ; i < ggml_backend_reg_dev_count (reg); i++) {
96108 register_device (ggml_backend_reg_dev_get (reg, i));
97109 }
@@ -126,7 +138,7 @@ size_t ggml_backend_reg_count() {
126138
127139ggml_backend_reg_t ggml_backend_reg_get (size_t index) {
128140 GGML_ASSERT (index < ggml_backend_reg_count ());
129- return get_reg ().backends [index];
141+ return get_reg ().backends [index]. reg ;
130142}
131143
132144ggml_backend_reg_t ggml_backend_reg_by_name (const char * name) {
@@ -136,7 +148,7 @@ ggml_backend_reg_t ggml_backend_reg_by_name(const char * name) {
136148 return reg;
137149 }
138150 }
139- return NULL ;
151+ return nullptr ;
140152}
141153
142154// Device enumeration
@@ -156,7 +168,7 @@ ggml_backend_dev_t ggml_backend_dev_by_name(const char * name) {
156168 return dev;
157169 }
158170 }
159- return NULL ;
171+ return nullptr ;
160172}
161173
162174ggml_backend_dev_t ggml_backend_dev_by_type (enum ggml_backend_dev_type type) {
@@ -166,22 +178,22 @@ ggml_backend_dev_t ggml_backend_dev_by_type(enum ggml_backend_dev_type type) {
166178 return dev;
167179 }
168180 }
169- return NULL ;
181+ return nullptr ;
170182}
171183
172184// Convenience functions
173185ggml_backend_t ggml_backend_init_by_name (const char * name, const char * params) {
174186 ggml_backend_dev_t dev = ggml_backend_dev_by_name (name);
175187 if (!dev) {
176- return NULL ;
188+ return nullptr ;
177189 }
178190 return ggml_backend_dev_init (dev, params);
179191}
180192
181193ggml_backend_t ggml_backend_init_by_type (enum ggml_backend_dev_type type, const char * params) {
182194 ggml_backend_dev_t dev = ggml_backend_dev_by_type (type);
183195 if (!dev) {
184- return NULL ;
196+ return nullptr ;
185197 }
186198 return ggml_backend_dev_init (dev, params);
187199}
@@ -192,9 +204,9 @@ ggml_backend_t ggml_backend_init_best(void) {
192204 dev = ggml_backend_dev_by_type (GGML_BACKEND_DEVICE_TYPE_CPU);
193205 }
194206 if (!dev) {
195- return NULL ;
207+ return nullptr ;
196208 }
197- return ggml_backend_dev_init (dev, NULL );
209+ return ggml_backend_dev_init (dev, nullptr );
198210}
199211
200212#ifdef _WIN32
@@ -214,45 +226,66 @@ ggml_backend_reg_t ggml_backend_load(const char * path) {
214226 HMODULE handle = LoadLibraryA (path);
215227 if (!handle) {
216228 GGML_LOG_ERROR (" %s: failed to load %s: %lu\n " , __func__, path, GetLastError ());
217- return NULL ;
229+ return nullptr ;
218230 }
219231 ggml_backend_init_t backend_init = (ggml_backend_init_t ) GetProcAddress (handle, " ggml_backend_init" );
220232 if (!backend_init) {
221233 GGML_LOG_ERROR (" %s: failed to find ggml_backend_init in %s: %lu\n " , __func__, path, GetLastError ());
222234 FreeLibrary (handle);
223- return NULL ;
224- }
225- ggml_backend_reg_t reg = backend_init ();
226- if (!reg) {
227- GGML_LOG_ERROR (" %s: failed to initialize backend from %s\n " , __func__, path);
228- FreeLibrary (handle);
229- return NULL ;
235+ return nullptr ;
230236 }
231- GGML_LOG_DEBUG (" %s: loaded %s backend from %s\n " , __func__, ggml_backend_reg_name (reg), path);
232- ggml_backend_register (reg);
233- return reg;
234237#else
235238 void * handle = dlopen (path, RTLD_NOW | RTLD_LOCAL);
236239 if (!handle) {
237240 GGML_LOG_ERROR (" %s: failed to load %s: %s\n " , __func__, path, dlerror ());
238- return NULL ;
241+ return nullptr ;
239242 }
240243 auto * backend_init = (ggml_backend_init_t ) dlsym (handle, " ggml_backend_init" );
241244 if (!backend_init) {
242245 GGML_LOG_ERROR (" %s: failed to find ggml_backend_init in %s: %s\n " , __func__, path, dlerror ());
243246 dlclose (handle);
244- return NULL ;
247+ return nullptr ;
245248 }
249+ #endif
246250 ggml_backend_reg_t reg = backend_init ();
247251 if (!reg) {
248252 GGML_LOG_ERROR (" %s: failed to initialize backend from %s\n " , __func__, path);
249253 dlclose (handle);
250- return NULL ;
254+ return nullptr ;
251255 }
252256 GGML_LOG_DEBUG (" %s: loaded %s backend from %s\n " , __func__, ggml_backend_reg_name (reg), path);
253- ggml_backend_register ( reg);
257+ get_reg (). register_backend ( reg, handle );
254258 return reg;
259+ }
260+
261+ void ggml_backend_unload (ggml_backend_reg_t reg) {
262+ auto it = std::find_if (get_reg ().backends .begin (), get_reg ().backends .end (),
263+ [reg](ggml_backend_reg_entry entry) { return entry.reg == reg; });
264+
265+ if (it == get_reg ().backends .end ()) {
266+ GGML_LOG_ERROR (" %s: backend not found\n " , __func__);
267+ return ;
268+ }
269+
270+ GGML_LOG_DEBUG (" %s: unloading %s backend\n " , __func__, ggml_backend_reg_name (reg));
271+
272+ // remove devices
273+ get_reg ().devices .erase (
274+ std::remove_if (get_reg ().devices .begin (), get_reg ().devices .end (),
275+ [reg](ggml_backend_dev_t dev) { return ggml_backend_dev_backend_reg (dev) == reg; }),
276+ get_reg ().devices .end ());
277+
278+ // unload library
279+ if (it->handle ) {
280+ #ifdef _WIN32
281+ FreeLibrary ((HMODULE) it->handle );
282+ #else
283+ dlclose (it->handle );
255284#endif
285+ }
286+
287+ // remove backend
288+ get_reg ().backends .erase (it);
256289}
257290
258291void ggml_backend_load_all () {
0 commit comments