@@ -806,6 +806,99 @@ void ModelLoader::process_model_files(bool enable_mmap) {
806806 LOG_INFO (" model files processing completed in %.2fs" , process_time_ms / 1000 .f );
807807}
808808
809+ std::vector<MmapTensorStore> ModelLoader::mmap_tensors (std::map<std::string, ggml_tensor*>& tensors,
810+ std::set<std::string> ignore_tensors)
811+ {
812+ process_model_files (true );
813+
814+ std::vector<MmapTensorStore> result;
815+ uint64_t mapped_bytes = 0 ;
816+ size_t mapped_tensors = 0 ;
817+
818+ LOG_DEBUG (" memory-mapping tensors..." );
819+
820+ int64_t t_start = ggml_time_ms ();
821+
822+ for (const auto & fdata : file_data) {
823+ if (!fdata.mmapped ) continue ;
824+
825+ const std::vector<TensorStorage>& file_tensors = fdata.tensors ;
826+ std::shared_ptr<MmapWrapper> mmapped = fdata.mmapped ;
827+
828+ uint8_t * mmap_data = const_cast <uint8_t *>(mmapped->data ());
829+
830+ ggml_backend_buffer_t buf_mmap = ggml_backend_cpu_buffer_from_ptr (mmap_data, mmapped->size ());
831+ if (!buf_mmap) {
832+ LOG_WARN (" mmap: failed to create backend buffer for file %s" , fdata.path .c_str ());
833+ continue ;
834+ }
835+ ggml_backend_buffer_set_usage (buf_mmap, GGML_BACKEND_BUFFER_USAGE_WEIGHTS );
836+
837+ size_t file_mapped_bytes = 0 ;
838+ size_t file_mapped_tensors = 0 ;
839+
840+ for (const auto & tensor_storage : file_tensors) {
841+ const std::string& name = tensor_storage.name ;
842+
843+ bool is_ignored = false ;
844+ for (const auto & ignore_prefix : ignore_tensors) {
845+ if (starts_with (name, ignore_prefix)) {
846+ is_ignored = true ;
847+ break ;
848+ }
849+ }
850+ if (is_ignored)
851+ continue ;
852+
853+ auto it = tensors.find (name);
854+ if (it == tensors.end ())
855+ continue ;
856+
857+ ggml_tensor* dst_tensor = it->second ;
858+ if (dst_tensor == nullptr )
859+ continue ;
860+
861+ if (tensor_storage.type != dst_tensor->type )
862+ continue ;
863+
864+ size_t tensor_size = tensor_storage.nbytes ();
865+ size_t tensor_offset = tensor_storage.offset ;
866+
867+ if (tensor_storage.ne [0 ] != dst_tensor->ne [0 ] ||
868+ tensor_storage.ne [1 ] != dst_tensor->ne [1 ] ||
869+ tensor_storage.ne [2 ] != dst_tensor->ne [2 ] ||
870+ tensor_storage.ne [3 ] != dst_tensor->ne [3 ] ||
871+ tensor_size != ggml_nbytes (dst_tensor)) {
872+ // let load_tensors worry about this
873+ continue ;
874+ }
875+
876+ dst_tensor->buffer = buf_mmap;
877+ dst_tensor->data = mmap_data + tensor_offset;
878+
879+ file_mapped_bytes += tensor_size;
880+ file_mapped_tensors++;
881+ }
882+
883+ if (file_mapped_bytes > 0 ) {
884+ mapped_tensors += file_mapped_tensors;
885+ mapped_bytes += file_mapped_bytes;
886+ result.push_back ({mmapped, buf_mmap});
887+ }
888+ }
889+
890+ int64_t t_end = ggml_time_ms ();
891+ int64_t duration_ms = t_end - t_start;
892+
893+ LOG_INFO (" memory-mapped %zu tensors in %zu files (%.2f MB), taking %.2fs" ,
894+ mapped_tensors,
895+ result.size (),
896+ mapped_bytes / (1024.0 * 1024.0 ),
897+ duration_ms / 1000.0 );
898+
899+ return result;
900+ }
901+
809902bool ModelLoader::load_tensors (on_new_tensor_cb_t on_new_tensor_cb, int n_threads_p, bool enable_mmap) {
810903
811904 process_model_files (enable_mmap);
@@ -898,6 +991,12 @@ bool ModelLoader::load_tensors(on_new_tensor_cb_t on_new_tensor_cb, int n_thread
898991 continue ;
899992 }
900993
994+ // skip mmapped tensors
995+ if (dst_tensor->buffer != nullptr
996+ && ggml_backend_buffer_get_usage (dst_tensor->buffer ) == GGML_BACKEND_BUFFER_USAGE_WEIGHTS ) {
997+ continue ;
998+ }
999+
9011000 size_t nbytes_to_read = tensor_storage.nbytes_to_read ();
9021001
9031002 auto read_data = [&](char * buf, size_t n) {
0 commit comments