CPU: ACCEL -> GPU host -> CPU extra -> CPU
| 325 | |
| 326 | // CPU: ACCEL -> GPU host -> CPU extra -> CPU |
| 327 | static buft_list_t make_cpu_buft_list(const std::vector<ggml_backend_dev_t> & devices, bool use_extra_bufts, bool no_host) { |
| 328 | buft_list_t buft_list; |
| 329 | |
| 330 | // add ACCEL buffer types |
| 331 | for (size_t i = 0; i < ggml_backend_dev_count(); ++i) { |
| 332 | ggml_backend_dev_t dev = ggml_backend_dev_get(i); |
| 333 | if (ggml_backend_dev_type(dev) == GGML_BACKEND_DEVICE_TYPE_ACCEL) { |
| 334 | auto * buft = ggml_backend_dev_buffer_type(dev); |
| 335 | // skip |
| 336 | if (buft != ggml_backend_cpu_buffer_type()) { |
| 337 | buft_list.emplace_back(dev, buft); |
| 338 | } |
| 339 | } |
| 340 | } |
| 341 | |
| 342 | // add a host buffer type |
| 343 | // storing the tensors in a host buffer is useful when the processing of large batches |
| 344 | // is offloaded to a GPU device, since it reduces the time spent on data transfers |
| 345 | // generally, this will be done using the first device in the list |
| 346 | // a better approach would be to handle this on a weight-by-weight basis using the offload_op |
| 347 | // function of the device to determine if it would benefit from being stored in a host buffer |
| 348 | if (!no_host) { |
| 349 | for (auto * dev : devices) { |
| 350 | ggml_backend_buffer_type_t buft = ggml_backend_dev_host_buffer_type(dev); |
| 351 | if (buft) { |
| 352 | buft_list.emplace_back(dev, buft); |
| 353 | break; |
| 354 | } |
| 355 | } |
| 356 | } |
| 357 | |
| 358 | // add extra buffer types |
| 359 | if (use_extra_bufts) { |
| 360 | auto * cpu_dev = ggml_backend_dev_by_type(GGML_BACKEND_DEVICE_TYPE_CPU); |
| 361 | if (cpu_dev == nullptr) { |
| 362 | throw std::runtime_error(format("%s: no CPU backend found", __func__)); |
| 363 | } |
| 364 | |
| 365 | auto * cpu_reg = ggml_backend_dev_backend_reg(cpu_dev); |
| 366 | auto ggml_backend_dev_get_extra_bufts_fn = (ggml_backend_dev_get_extra_bufts_t) |
| 367 | ggml_backend_reg_get_proc_address(cpu_reg, "ggml_backend_dev_get_extra_bufts"); |
| 368 | if (ggml_backend_dev_get_extra_bufts_fn) { |
| 369 | ggml_backend_buffer_type_t * extra_bufts = ggml_backend_dev_get_extra_bufts_fn(cpu_dev); |
| 370 | while (extra_bufts && *extra_bufts) { |
| 371 | buft_list.emplace_back(cpu_dev, *extra_bufts); |
| 372 | ++extra_bufts; |
| 373 | } |
| 374 | } |
| 375 | } |
| 376 | |
| 377 | // add the CPU buffer type |
| 378 | for (size_t i = 0; i < ggml_backend_dev_count(); ++i) { |
| 379 | ggml_backend_dev_t dev = ggml_backend_dev_get(i); |
| 380 | if (ggml_backend_dev_type(dev) == GGML_BACKEND_DEVICE_TYPE_CPU) { |
| 381 | buft_list.emplace_back(dev, ggml_backend_dev_buffer_type(dev)); |
| 382 | } |
| 383 | } |
| 384 |
no test coverage detected