mirror of
https://github.com/ikawrakow/ik_llama.cpp.git
synced 2026-05-11 00:20:19 +00:00
Give the user the option to override where model weights are stored (#232)
* Give the user the option to override where model weights are stored * Fix ggml_nbytes() problem and cleanup For a tensor with zero elements ggml_nbytes() was returning uint64_t::max, and this was causing graph allocation failure. * Add timing info to CUDA graph evaluation * Add more timing info --------- Co-authored-by: Iwan Kawrakow <iwan.kawrakow@gmail.com>
This commit is contained in:
@@ -265,6 +265,9 @@ bool gpt_params_parse_ex(int argc, char ** argv, gpt_params & params) {
|
||||
params.kv_overrides.emplace_back();
|
||||
params.kv_overrides.back().key[0] = 0;
|
||||
}
|
||||
if (!params.tensor_buft_overrides.empty()) {
|
||||
params.tensor_buft_overrides.push_back({nullptr, nullptr});
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -287,6 +290,40 @@ bool gpt_params_parse(int argc, char ** argv, gpt_params & params) {
|
||||
return true;
|
||||
}
|
||||
|
||||
namespace {
|
||||
bool parse_buft_overrides(const std::string& value, std::vector<llama_model_tensor_buft_override>& overrides) {
|
||||
/* static */ std::map<std::string, ggml_backend_buffer_type_t> buft_list;
|
||||
if (buft_list.empty()) {
|
||||
// enumerate all the devices and add their buffer types to the list
|
||||
for (size_t i = 0; i < ggml_backend_reg_get_count(); ++i) {
|
||||
//auto * dev = ggml_backend_reg_get_name(i);
|
||||
auto * buft = ggml_backend_reg_get_default_buffer_type(i);
|
||||
if (buft) {
|
||||
buft_list[ggml_backend_buft_name(buft)] = buft;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const auto & override : string_split<std::string>(value, ',')) {
|
||||
std::string::size_type pos = override.find('=');
|
||||
if (pos == std::string::npos) {
|
||||
fprintf(stderr, "Invalid buft override argument %s\n", value.c_str());
|
||||
return false;
|
||||
}
|
||||
std::string tensor_name = override.substr(0, pos);
|
||||
std::string buffer_type = override.substr(pos + 1);
|
||||
if (buft_list.find(buffer_type) == buft_list.end()) {
|
||||
fprintf(stderr, "Available buffer types:\n");
|
||||
for (const auto & it : buft_list) {
|
||||
fprintf(stderr, " %s\n", ggml_backend_buft_name(it.second));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
overrides.push_back({strdup(tensor_name.c_str()), buft_list.at(buffer_type)});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
#define CHECK_ARG if (++i >= argc) { invalid_param = true; return true; }
|
||||
|
||||
bool gpt_params_find_arg(int argc, char ** argv, const std::string & arg, gpt_params & params, int & i, bool & invalid_param) {
|
||||
@@ -1120,6 +1157,14 @@ bool gpt_params_find_arg(int argc, char ** argv, const std::string & arg, gpt_pa
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (arg == "--override-tensor" || arg == "-ot") {
|
||||
CHECK_ARG
|
||||
if (!parse_buft_overrides(std::string{argv[i]}, params.tensor_buft_overrides)) {
|
||||
fprintf(stderr, "error: Invalid tensor buffer type override: %s\n", argv[i]);
|
||||
invalid_param = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (arg == "--host") {
|
||||
CHECK_ARG
|
||||
params.hostname = argv[i];
|
||||
@@ -2238,6 +2283,12 @@ struct llama_model_params llama_model_params_from_gpt_params(const gpt_params &
|
||||
GGML_ASSERT(params.kv_overrides.back().key[0] == 0 && "KV overrides not terminated with empty key");
|
||||
mparams.kv_overrides = params.kv_overrides.data();
|
||||
}
|
||||
if (params.tensor_buft_overrides.empty()) {
|
||||
mparams.tensor_buft_overrides = NULL;
|
||||
} else {
|
||||
GGML_ASSERT(params.tensor_buft_overrides.back().pattern == nullptr && "Tensor buffer overrides not terminated with empty pattern");
|
||||
mparams.tensor_buft_overrides = params.tensor_buft_overrides.data();
|
||||
}
|
||||
|
||||
return mparams;
|
||||
}
|
||||
|
||||
@@ -135,6 +135,7 @@ struct gpt_params {
|
||||
std::vector<std::string> in_files; // all input files
|
||||
std::vector<std::string> antiprompt; // strings upon which more user input is prompted (a.k.a. reverse prompts)
|
||||
std::vector<llama_model_kv_override> kv_overrides;
|
||||
std::vector<llama_model_tensor_buft_override> tensor_buft_overrides;
|
||||
|
||||
bool lora_init_without_apply = false; // only load lora to memory, but do not apply it to ctx (user can manually apply lora later using llama_lora_adapter_apply)
|
||||
std::vector<llama_lora_adapter_info> lora_adapters; // lora adapter path with user defined scale
|
||||
|
||||
@@ -236,6 +236,7 @@ struct cmd_params {
|
||||
std::vector<std::vector<float>> tensor_split;
|
||||
std::vector<bool> use_mmap;
|
||||
std::vector<bool> embeddings;
|
||||
std::vector<llama_model_tensor_buft_override> buft_overrides;
|
||||
ggml_numa_strategy numa;
|
||||
int reps;
|
||||
bool verbose;
|
||||
@@ -267,6 +268,7 @@ static const cmd_params cmd_params_defaults = {
|
||||
/* tensor_split */ {std::vector<float>(llama_max_devices(), 0.0f)},
|
||||
/* use_mmap */ {true},
|
||||
/* embeddings */ {false},
|
||||
/* buft_overrides */ {},
|
||||
/* numa */ GGML_NUMA_STRATEGY_DISABLED,
|
||||
/* reps */ 5,
|
||||
/* verbose */ false,
|
||||
@@ -309,6 +311,7 @@ static void print_usage(int /* argc */, char ** argv) {
|
||||
printf(" -v, --verbose (default: %s)\n", cmd_params_defaults.verbose ? "1" : "0");
|
||||
printf(" -w, --warmup <0|1> (default: %s)\n", cmd_params_defaults.warmup ? "1" : "0");
|
||||
printf(" -rtr, --run-time-repack <0|1> (default: %s)\n", cmd_params_defaults.repack ? "1" : "0");
|
||||
printf(" -ot, --override-tensor pattern (default: none)\n");
|
||||
printf(" -fmoe, --fused-moe <0|1> (default: %s)\n", cmd_params_defaults.fmoe? "1" : "0");
|
||||
printf("\n");
|
||||
printf("Multiple values can be given for each parameter by separating them with ',' or by specifying the parameter multiple times.\n");
|
||||
@@ -349,6 +352,39 @@ static ggml_type ggml_type_from_name(const std::string & s) {
|
||||
return GGML_TYPE_COUNT;
|
||||
}
|
||||
|
||||
namespace {
|
||||
bool parse_buft_overrides(const std::string& value, std::vector<llama_model_tensor_buft_override>& overrides) {
|
||||
/* static */ std::map<std::string, ggml_backend_buffer_type_t> buft_list;
|
||||
if (buft_list.empty()) {
|
||||
// enumerate all the devices and add their buffer types to the list
|
||||
for (size_t i = 0; i < ggml_backend_reg_get_count(); ++i) {
|
||||
//auto * dev = ggml_backend_reg_get_name(i);
|
||||
auto * buft = ggml_backend_reg_get_default_buffer_type(i);
|
||||
if (buft) {
|
||||
buft_list[ggml_backend_buft_name(buft)] = buft;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (const auto & override : string_split<std::string>(value, ',')) {
|
||||
std::string::size_type pos = override.find('=');
|
||||
if (pos == std::string::npos) {
|
||||
fprintf(stderr, "Invalid buft override argument %s\n", value.c_str());
|
||||
return false;
|
||||
}
|
||||
std::string tensor_name = override.substr(0, pos);
|
||||
std::string buffer_type = override.substr(pos + 1);
|
||||
if (buft_list.find(buffer_type) == buft_list.end()) {
|
||||
fprintf(stderr, "Available buffer types:\n");
|
||||
for (const auto & it : buft_list) {
|
||||
fprintf(stderr, " %s\n", ggml_backend_buft_name(it.second));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
overrides.push_back({strdup(tensor_name.c_str()), buft_list.at(buffer_type)});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static cmd_params parse_cmd_params(int argc, char ** argv) {
|
||||
cmd_params params;
|
||||
@@ -616,6 +652,16 @@ static cmd_params parse_cmd_params(int argc, char ** argv) {
|
||||
break;
|
||||
}
|
||||
params.fmoe = std::stoi(argv[i]);
|
||||
} else if (arg == "-ot" || arg == "--override-tensor") {
|
||||
if (++i >= argc) {
|
||||
invalid_param = true;
|
||||
break;
|
||||
}
|
||||
if (!parse_buft_overrides(std::string{argv[i]}, params.buft_overrides)) {
|
||||
fprintf(stderr, "error: Invalid tensor buffer type override: %s\n", argv[i]);
|
||||
invalid_param = true;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
invalid_param = true;
|
||||
break;
|
||||
@@ -648,6 +694,7 @@ static cmd_params parse_cmd_params(int argc, char ** argv) {
|
||||
if (params.use_mmap.empty()) { params.use_mmap = cmd_params_defaults.use_mmap; }
|
||||
if (params.embeddings.empty()) { params.embeddings = cmd_params_defaults.embeddings; }
|
||||
if (params.n_threads.empty()) { params.n_threads = cmd_params_defaults.n_threads; }
|
||||
if (!params.buft_overrides.empty()) params.buft_overrides.emplace_back(llama_model_tensor_buft_override{nullptr, nullptr});
|
||||
|
||||
return params;
|
||||
}
|
||||
@@ -685,6 +732,7 @@ struct cmd_params_instance {
|
||||
bool embeddings;
|
||||
bool repack = false;
|
||||
bool fmoe = false;
|
||||
const llama_model_tensor_buft_override* buft_overrides;
|
||||
|
||||
llama_model_params to_llama_mparams() const {
|
||||
llama_model_params mparams = llama_model_default_params();
|
||||
@@ -698,6 +746,7 @@ struct cmd_params_instance {
|
||||
mparams.tensor_split = tensor_split.data();
|
||||
mparams.use_mmap = use_mmap;
|
||||
mparams.repack_tensors = repack;
|
||||
mparams.tensor_buft_overrides = buft_overrides;
|
||||
|
||||
return mparams;
|
||||
}
|
||||
@@ -777,6 +826,7 @@ static std::vector<cmd_params_instance> get_cmd_params_instances(const cmd_param
|
||||
/* .embeddings = */ embd,
|
||||
/* .repack = */ params.repack,
|
||||
/* .fmoe = */ params.fmoe,
|
||||
/* .buft_overrides=*/ params.buft_overrides.data(),
|
||||
};
|
||||
instances.push_back(instance);
|
||||
}
|
||||
@@ -807,6 +857,7 @@ static std::vector<cmd_params_instance> get_cmd_params_instances(const cmd_param
|
||||
/* .embeddings = */ embd,
|
||||
/* .repack = */ params.repack,
|
||||
/* .fmoe = */ params.fmoe,
|
||||
/* .buft_overrides=*/ params.buft_overrides.data(),
|
||||
};
|
||||
instances.push_back(instance);
|
||||
}
|
||||
@@ -837,6 +888,7 @@ static std::vector<cmd_params_instance> get_cmd_params_instances(const cmd_param
|
||||
/* .embeddings = */ embd,
|
||||
/* .repack = */ params.repack,
|
||||
/* .fmoe = */ params.fmoe,
|
||||
/* .buft_overrides=*/ params.buft_overrides.data(),
|
||||
};
|
||||
instances.push_back(instance);
|
||||
}
|
||||
@@ -867,6 +919,7 @@ static std::vector<cmd_params_instance> get_cmd_params_instances(const cmd_param
|
||||
/* .embeddings = */ embd,
|
||||
/* .repack = */ params.repack,
|
||||
/* .fmoe = */ params.fmoe,
|
||||
/* .buft_overrides=*/ params.buft_overrides.data(),
|
||||
};
|
||||
instances.push_back(instance);
|
||||
}
|
||||
|
||||
@@ -174,6 +174,8 @@ static size_t ggml_dyn_tallocr_alloc(struct ggml_dyn_tallocr * alloc, size_t siz
|
||||
// this should never happen
|
||||
fprintf(stderr, "%s: not enough space in the buffer to allocate %zu bytes, largest block available %zu bytes\n",
|
||||
__func__, size, max_avail);
|
||||
fprintf(stderr, "%s: tensor was %s with %zu elements and %zu bytes\n", __func__, tensor->name,
|
||||
ggml_nelements(tensor), ggml_nbytes(tensor));
|
||||
GGML_ABORT("not enough space in the buffer");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define IK_PRINT_TIMING 0
|
||||
|
||||
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||
|
||||
@@ -229,7 +230,17 @@ GGML_CALL void ggml_backend_tensor_set(struct ggml_tensor * tensor, const void *
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
#if IK_PRINT_TIMING
|
||||
int64_t tim1 = ggml_time_us();
|
||||
#endif
|
||||
buf->iface.set_tensor(buf, tensor, data, offset, size);
|
||||
#if IK_PRINT_TIMING
|
||||
int64_t tim2 = ggml_time_us();
|
||||
//printf("%s(%s) %zu %d us\n", __func__, tensor->name, size, (int)(tim2-tim1));
|
||||
printf("%s(%s): %d us\n", __func__, tensor->name, (int)(tim2-tim1));
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
GGML_CALL void ggml_backend_tensor_get(const struct ggml_tensor * tensor, void * data, size_t offset, size_t size) {
|
||||
@@ -243,7 +254,15 @@ GGML_CALL void ggml_backend_tensor_get(const struct ggml_tensor * tensor, void *
|
||||
return;
|
||||
}
|
||||
|
||||
#if IK_PRINT_TIMING
|
||||
int64_t tim1 = ggml_time_us();
|
||||
#endif
|
||||
buf->iface.get_tensor(buf, tensor, data, offset, size);
|
||||
#if IK_PRINT_TIMING
|
||||
int64_t tim2 = ggml_time_us();
|
||||
//printf("%s(%s) %zu %d us\n", __func__, tensor->name, size, (int)(tim2-tim1));
|
||||
printf("%s(%s): %d us\n", __func__, tensor->name, (int)(tim2-tim1));
|
||||
#endif
|
||||
}
|
||||
|
||||
void ggml_backend_synchronize(ggml_backend_t backend) {
|
||||
@@ -1751,7 +1770,11 @@ static bool ggml_backend_sched_alloc_splits(ggml_backend_sched_t sched) {
|
||||
static enum ggml_status ggml_backend_sched_compute_splits(ggml_backend_sched_t sched) {
|
||||
struct ggml_backend_sched_split * splits = sched->splits;
|
||||
|
||||
|
||||
for (int i = 0; i < sched->n_splits; i++) {
|
||||
#if IK_PRINT_TIMING
|
||||
int64_t tim1 = ggml_time_us();
|
||||
#endif
|
||||
struct ggml_backend_sched_split * split = &splits[i];
|
||||
int split_backend_id = split->backend_id;
|
||||
ggml_backend_t split_backend = sched->backends[split_backend_id];
|
||||
@@ -1792,6 +1815,10 @@ static enum ggml_status ggml_backend_sched_compute_splits(ggml_backend_sched_t s
|
||||
}
|
||||
|
||||
if (!sched->callback_eval) {
|
||||
#if IK_PRINT_TIMING
|
||||
int64_t tim2 = ggml_time_us();
|
||||
printf("%s(.1.): %d us\n", __func__, (int)(tim2-tim1));
|
||||
#endif
|
||||
enum ggml_status ec = ggml_backend_graph_compute_async(split_backend, &split->graph);
|
||||
if (ec != GGML_STATUS_SUCCESS) {
|
||||
return ec;
|
||||
@@ -1814,6 +1841,11 @@ static enum ggml_status ggml_backend_sched_compute_splits(ggml_backend_sched_t s
|
||||
|
||||
struct ggml_cgraph gv = ggml_graph_view(&split->graph, j0, j1 + 1);
|
||||
|
||||
#if IK_PRINT_TIMING
|
||||
int64_t tim2 = ggml_time_us();
|
||||
printf("%s(.2.): %d us\n", __func__, (int)(tim2-tim1));
|
||||
#endif
|
||||
|
||||
enum ggml_status ec = ggml_backend_graph_compute_async(split_backend, &gv);
|
||||
if (ec != GGML_STATUS_SUCCESS) {
|
||||
return ec;
|
||||
|
||||
@@ -50,6 +50,8 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#define IK_PRINT_TIMING 0
|
||||
|
||||
static_assert(sizeof(half) == sizeof(ggml_fp16_t), "wrong fp16 size");
|
||||
|
||||
static void ggml_cuda_default_log_callback(enum ggml_log_level level, const char * msg, void * user_data) {
|
||||
@@ -2446,6 +2448,10 @@ static bool ggml_cuda_compute_forward(ggml_backend_cuda_context & ctx, struct gg
|
||||
ggml_cuda_set_peer_access(dst->src[1]->ne[1], ctx.device);
|
||||
}
|
||||
|
||||
#if IK_PRINT_TIMING
|
||||
int64_t tim1 = ggml_time_us();
|
||||
#endif
|
||||
|
||||
switch (dst->op) {
|
||||
case GGML_OP_REPEAT:
|
||||
ggml_cuda_op_repeat(ctx, dst);
|
||||
@@ -2618,6 +2624,11 @@ static bool ggml_cuda_compute_forward(ggml_backend_cuda_context & ctx, struct gg
|
||||
CUDA_CHECK(err);
|
||||
}
|
||||
|
||||
#if IK_PRINT_TIMING
|
||||
int64_t tim2 = ggml_time_us();
|
||||
printf("%s(%s): %d us\n", ggml_op_name(dst->op), dst->name, (int)(tim2 - tim1));
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -4267,6 +4267,9 @@ GGML_CALL int64_t ggml_blck_size(enum ggml_type type) {
|
||||
}
|
||||
|
||||
GGML_CALL size_t ggml_nbytes(const struct ggml_tensor * tensor) {
|
||||
for (int i = 0; i < GGML_MAX_DIMS; ++i) {
|
||||
if (tensor->ne[i] <= 0) return 0;
|
||||
}
|
||||
size_t nbytes;
|
||||
size_t blck_size = ggml_blck_size(tensor->type);
|
||||
if (blck_size == 1) {
|
||||
@@ -21480,6 +21483,9 @@ enum ggml_status ggml_graph_compute(struct ggml_cgraph * cgraph, struct ggml_cpl
|
||||
|
||||
#ifdef GGML_USE_OPENMP
|
||||
if (n_threads > 1) {
|
||||
//#if IK_PRINT_TIMING
|
||||
// int64_t tim1 = ggml_time_us();
|
||||
//#endif
|
||||
#pragma omp parallel num_threads(n_threads)
|
||||
{
|
||||
#pragma omp single
|
||||
@@ -21496,6 +21502,10 @@ enum ggml_status ggml_graph_compute(struct ggml_cgraph * cgraph, struct ggml_cpl
|
||||
};
|
||||
ggml_graph_compute_thread(&worker);
|
||||
}
|
||||
//#if IK_PRINT_TIMING
|
||||
// int64_t tim2 = ggml_time_us();
|
||||
// printf("%s(...): %d us\n", __func__, (int)(tim2-tim1));
|
||||
//#endif
|
||||
} else {
|
||||
struct ggml_compute_state worker = {
|
||||
.thrd = 0,
|
||||
|
||||
@@ -305,6 +305,11 @@ extern "C" {
|
||||
};
|
||||
};
|
||||
|
||||
struct llama_model_tensor_buft_override {
|
||||
const char * pattern;
|
||||
ggml_backend_buffer_type_t buft;
|
||||
};
|
||||
|
||||
struct llama_model_params {
|
||||
int32_t n_gpu_layers; // number of layers to store in VRAM
|
||||
enum llama_split_mode split_mode; // how to split the model across multiple GPUs
|
||||
@@ -332,6 +337,8 @@ extern "C" {
|
||||
// override key-value pairs of the model meta data
|
||||
const struct llama_model_kv_override * kv_overrides;
|
||||
|
||||
const struct llama_model_tensor_buft_override * tensor_buft_overrides;
|
||||
|
||||
// Keep the booleans together to avoid misalignment during copy-by-value.
|
||||
bool vocab_only; // only load the vocabulary, no weights
|
||||
bool use_mmap; // use mmap if possible
|
||||
|
||||
1302
src/llama.cpp
1302
src/llama.cpp
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user