| 969 | } |
| 970 | |
| 971 | bool llama_model_loader::load_all_data( |
| 972 | struct ggml_context * ctx, |
| 973 | llama_buf_map & bufs, |
| 974 | llama_mlocks * lmlocks, |
| 975 | llama_progress_callback progress_callback, |
| 976 | void * progress_callback_user_data) { |
| 977 | GGML_ASSERT(size_data != 0 && "call init_mappings() first"); |
| 978 | |
| 979 | std::vector<no_init<uint8_t>> read_buf; |
| 980 | std::vector<std::future<std::pair<ggml_tensor *, bool>>> validation_result; |
| 981 | |
| 982 | // 4 staging buffers for async uploads, each sized 1MB seems to be a good default for single NVMe drives. |
| 983 | // NVMe raid configurations might require more / larger buffers. |
| 984 | constexpr size_t n_buffers = 4; |
| 985 | |
| 986 | size_t alignment = 1; |
| 987 | for (const auto & file : files) { |
| 988 | alignment = std::max(file->read_alignment(), alignment); |
| 989 | } |
| 990 | |
| 991 | // Buffer size: balance between memory usage and I/O efficiency |
| 992 | // 64MB works well for NVMe drives |
| 993 | const size_t buffer_size = alignment != 1 ? 64 * 1024 * 1024 + 2 * alignment : 1 * 1024 * 1024; |
| 994 | |
| 995 | std::vector<ggml_backend_buffer_t> host_buffers; |
| 996 | std::vector<ggml_backend_event_t> events; |
| 997 | std::vector<void *> host_ptrs; |
| 998 | size_t buffer_idx = 0; // buffer to use for async loads |
| 999 | ggml_backend_t upload_backend = [&](const char * func) -> ggml_backend_t { |
| 1000 | if (use_mmap || check_tensors) { |
| 1001 | return nullptr; |
| 1002 | } |
| 1003 | // When not using mmaped io use async uploads from pinned memory to GPU memory. |
| 1004 | // First determine if the backend supports the necessary features for async uploads. |
| 1005 | auto * buf = bufs.count(0) ? bufs.at(0) : nullptr; |
| 1006 | if (!buf) { |
| 1007 | LLAMA_LOG_DEBUG("%s: no buffer found for async uploads\n", func); |
| 1008 | return nullptr; |
| 1009 | } |
| 1010 | |
| 1011 | auto * buft = ggml_backend_buffer_get_type(buf); |
| 1012 | auto * dev = ggml_backend_buft_get_device(buft); |
| 1013 | if (!dev) { |
| 1014 | LLAMA_LOG_DEBUG("%s: no device found for buffer type %s for async uploads\n", func, |
| 1015 | ggml_backend_buft_name(buft)); |
| 1016 | return nullptr; |
| 1017 | } |
| 1018 | |
| 1019 | if (buft != ggml_backend_dev_buffer_type(dev)) { |
| 1020 | LLAMA_LOG_DEBUG("%s: buffer type %s is not the default buffer type for device %s for async uploads\n", func, |
| 1021 | ggml_backend_buft_name(buft), ggml_backend_dev_name(dev)); |
| 1022 | return nullptr; |
| 1023 | } |
| 1024 | |
| 1025 | ggml_backend_dev_props props; |
| 1026 | ggml_backend_dev_get_props(dev, &props); |
| 1027 | if (!props.caps.async || !props.caps.host_buffer || !props.caps.events) { |
| 1028 | LLAMA_LOG_DEBUG("%s: device %s does not support async, host buffers or events\n", func, |
no test coverage detected