}
// load data
- if (!ctx_clip.no_alloc) {
+ {
std::vector<uint8_t> read_buf;
// start loading event
ggml_backend_buffer_type_t buft = ggml_backend_get_default_buffer_type(ctx_clip.backend);
ctx_clip.buf.reset(ggml_backend_alloc_ctx_tensors_from_buft(ctx_clip.ctx_data.get(), buft));
ggml_backend_buffer_set_usage(ctx_clip.buf.get(), GGML_BACKEND_BUFFER_USAGE_WEIGHTS);
- size_t data_loaded = 0;
- for (auto & t : tensors_to_load) {
- ggml_tensor * cur = ggml_get_tensor(ctx_clip.ctx_data.get(), t->name);
- GGML_ASSERT(cur && "tensor not found in ctx_data");
- auto it_off = tensor_offset.find(t->name);
- GGML_ASSERT(it_off != tensor_offset.end() && "no offset for tensor");
- const size_t offset = it_off->second;
- fin.seekg(offset, std::ios::beg);
- if (!fin) {
- throw std::runtime_error(string_format("%s: failed to seek for tensor %s\n", __func__, t->name));
- }
- size_t num_bytes = ggml_nbytes(cur);
- if (ggml_backend_buft_is_host(buft)) {
- // for the CPU and Metal backend, we can read directly into the tensor
- fin.read(reinterpret_cast<char *>(cur->data), num_bytes);
- } else {
- // read into a temporary buffer first, then copy to device memory
- read_buf.resize(num_bytes);
- fin.read(reinterpret_cast<char *>(read_buf.data()), num_bytes);
- ggml_backend_tensor_set(cur, read_buf.data(), 0, num_bytes);
- }
- data_loaded += num_bytes;
- if (progress_callback && total_data_size > 0) {
- const float progress = (float)data_loaded / (float)total_data_size;
- if (!progress_callback(progress, progress_callback_user_data)) {
- throw std::runtime_error(string_format("%s: model loading cancelled by progress_callback\n", __func__));
+ // read the weight from file
+ if (!ctx_clip.no_alloc) {
+ size_t data_loaded = 0;
+ for (auto & t : tensors_to_load) {
+ ggml_tensor * cur = ggml_get_tensor(ctx_clip.ctx_data.get(), t->name);
+ GGML_ASSERT(cur && "tensor not found in ctx_data");
+ auto it_off = tensor_offset.find(t->name);
+ GGML_ASSERT(it_off != tensor_offset.end() && "no offset for tensor");
+ const size_t offset = it_off->second;
+ fin.seekg(offset, std::ios::beg);
+ if (!fin) {
+ throw std::runtime_error(string_format("%s: failed to seek for tensor %s\n", __func__, t->name));
+ }
+ size_t num_bytes = ggml_nbytes(cur);
+ if (ggml_backend_buft_is_host(buft)) {
+ // for the CPU and Metal backend, we can read directly into the tensor
+ fin.read(reinterpret_cast<char *>(cur->data), num_bytes);
+ } else {
+ // read into a temporary buffer first, then copy to device memory
+ read_buf.resize(num_bytes);
+ fin.read(reinterpret_cast<char *>(read_buf.data()), num_bytes);
+ ggml_backend_tensor_set(cur, read_buf.data(), 0, num_bytes);
+ }
+ data_loaded += num_bytes;
+ if (progress_callback && total_data_size > 0) {
+ const float progress = (float)data_loaded / (float)total_data_size;
+ if (!progress_callback(progress, progress_callback_user_data)) {
+ throw std::runtime_error(string_format("%s: model loading cancelled by progress_callback\n", __func__));
+ }
}
}
+ LOG_DBG("%s: loaded %zu tensors from %s\n", __func__, tensors_to_load.size(), fname.c_str());
+ } else {
+ LOG_DBG("%s: no_alloc is set, skipping tensor data loading (%zu tensors)\n", __func__, tensors_to_load.size());
}
fin.close();
-
- LOG_DBG("%s: loaded %zu tensors from %s\n", __func__, tensors_to_load.size(), fname.c_str());
}
}
// optionally get the memory usage of mmproj
if (has_mmproj && params_base.fit_params) {
+ int64_t t_start = ggml_time_us();
auto mmproj_mem = mtmd_get_memory_usage(mmproj_path.c_str(), mparams);
+ int64_t t_elapsed = ggml_time_us() - t_start;
if (!mmproj_mem.empty()) {
size_t total = 0;
for (auto & [dev, size] : mmproj_mem) {
total += size;
}
- SRV_INF("[mtmd] estimated worst-case memory usage of mmproj is %.2f MiB\n", total / (1024.0 * 1024.0));
+ SRV_INF("[mtmd] estimated worst-case memory usage of mmproj is %.2f MiB (took %.2f ms)\n", total / (1024.0 * 1024.0), t_elapsed / 1000.0);
GGML_ASSERT(!params_base.fit_params_target.empty());
for (auto & [dev, size] : mmproj_mem) {
for (size_t i = 0; i < ggml_backend_dev_count(); i++) {