1
1
#include " ggml-backend-impl.h"
2
2
#include " ggml-backend.h"
3
3
#include " ggml-impl.h"
4
+ #include < algorithm>
4
5
#include < cstring>
5
6
#include < vector>
6
7
45
46
#include " ggml-kompute.h"
46
47
#endif
47
48
49
+ struct ggml_backend_reg_entry {
50
+ ggml_backend_reg_t reg;
51
+ void * handle;
52
+ };
53
+
48
54
struct ggml_backend_registry {
49
- std::vector<ggml_backend_reg_t > backends;
55
+ std::vector<ggml_backend_reg_entry > backends;
50
56
std::vector<ggml_backend_dev_t > devices;
51
57
52
58
ggml_backend_registry () {
@@ -82,7 +88,13 @@ struct ggml_backend_registry {
82
88
#endif
83
89
}
84
90
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 ) {
86
98
if (!reg) {
87
99
return ;
88
100
}
@@ -91,7 +103,7 @@ struct ggml_backend_registry {
91
103
GGML_LOG_DEBUG (" %s: registered backend %s (%zu devices)\n " ,
92
104
__func__, ggml_backend_reg_name (reg), ggml_backend_reg_dev_count (reg));
93
105
#endif
94
- backends.push_back (reg);
106
+ backends.push_back ({ reg, handle } );
95
107
for (size_t i = 0 ; i < ggml_backend_reg_dev_count (reg); i++) {
96
108
register_device (ggml_backend_reg_dev_get (reg, i));
97
109
}
@@ -126,7 +138,7 @@ size_t ggml_backend_reg_count() {
126
138
127
139
ggml_backend_reg_t ggml_backend_reg_get (size_t index) {
128
140
GGML_ASSERT (index < ggml_backend_reg_count ());
129
- return get_reg ().backends [index ];
141
+ return get_reg ().backends [index ]. reg ;
130
142
}
131
143
132
144
ggml_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) {
136
148
return reg;
137
149
}
138
150
}
139
- return NULL ;
151
+ return nullptr ;
140
152
}
141
153
142
154
// Device enumeration
@@ -156,7 +168,7 @@ ggml_backend_dev_t ggml_backend_dev_by_name(const char * name) {
156
168
return dev;
157
169
}
158
170
}
159
- return NULL ;
171
+ return nullptr ;
160
172
}
161
173
162
174
ggml_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) {
166
178
return dev;
167
179
}
168
180
}
169
- return NULL ;
181
+ return nullptr ;
170
182
}
171
183
172
184
// Convenience functions
173
185
ggml_backend_t ggml_backend_init_by_name (const char * name, const char * params) {
174
186
ggml_backend_dev_t dev = ggml_backend_dev_by_name (name);
175
187
if (!dev) {
176
- return NULL ;
188
+ return nullptr ;
177
189
}
178
190
return ggml_backend_dev_init (dev, params);
179
191
}
180
192
181
193
ggml_backend_t ggml_backend_init_by_type (enum ggml_backend_dev_type type, const char * params) {
182
194
ggml_backend_dev_t dev = ggml_backend_dev_by_type (type);
183
195
if (!dev) {
184
- return NULL ;
196
+ return nullptr ;
185
197
}
186
198
return ggml_backend_dev_init (dev, params);
187
199
}
@@ -192,9 +204,9 @@ ggml_backend_t ggml_backend_init_best(void) {
192
204
dev = ggml_backend_dev_by_type (GGML_BACKEND_DEVICE_TYPE_CPU);
193
205
}
194
206
if (!dev) {
195
- return NULL ;
207
+ return nullptr ;
196
208
}
197
- return ggml_backend_dev_init (dev, NULL );
209
+ return ggml_backend_dev_init (dev, nullptr );
198
210
}
199
211
200
212
#ifdef _WIN32
@@ -214,45 +226,66 @@ ggml_backend_reg_t ggml_backend_load(const char * path) {
214
226
HMODULE handle = LoadLibraryA (path);
215
227
if (!handle) {
216
228
GGML_LOG_ERROR (" %s: failed to load %s: %lu\n " , __func__, path, GetLastError ());
217
- return NULL ;
229
+ return nullptr ;
218
230
}
219
231
ggml_backend_init_t backend_init = (ggml_backend_init_t ) GetProcAddress (handle, " ggml_backend_init" );
220
232
if (!backend_init) {
221
233
GGML_LOG_ERROR (" %s: failed to find ggml_backend_init in %s: %lu\n " , __func__, path, GetLastError ());
222
234
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 ;
230
236
}
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;
234
237
#else
235
238
void * handle = dlopen (path, RTLD_NOW | RTLD_LOCAL);
236
239
if (!handle) {
237
240
GGML_LOG_ERROR (" %s: failed to load %s: %s\n " , __func__, path, dlerror ());
238
- return NULL ;
241
+ return nullptr ;
239
242
}
240
243
auto * backend_init = (ggml_backend_init_t ) dlsym (handle, " ggml_backend_init" );
241
244
if (!backend_init) {
242
245
GGML_LOG_ERROR (" %s: failed to find ggml_backend_init in %s: %s\n " , __func__, path, dlerror ());
243
246
dlclose (handle);
244
- return NULL ;
247
+ return nullptr ;
245
248
}
249
+ #endif
246
250
ggml_backend_reg_t reg = backend_init ();
247
251
if (!reg) {
248
252
GGML_LOG_ERROR (" %s: failed to initialize backend from %s\n " , __func__, path);
249
253
dlclose (handle);
250
- return NULL ;
254
+ return nullptr ;
251
255
}
252
256
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 );
254
258
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 );
255
284
#endif
285
+ }
286
+
287
+ // remove backend
288
+ get_reg ().backends .erase (it);
256
289
}
257
290
258
291
void ggml_backend_load_all () {
0 commit comments