Skip to content

Commit e6dd0e2

Browse files
authored
args: refactor mlock/mmap/directio into load-mode (#20834)
* args: overhaul mmap/mlock/dio into single arg Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * docs: update docs with llama-gen-docs Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * chore: satisfy code quality Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * args: make the `+` sign an actual modifier now Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * chore: general code clean up + comments Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * arg: fix deprecated flags support Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * arg: quick sanity check Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * bench: sync llama-bench argument parsing Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * fix: bugfix variable behaviour + llama-bench lm column size Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * arg: inverse commands should do the opposite instead of doing nothing Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * bench: fix incorrect dash Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * bench: fix missing modifiers for deprecated flags Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * llama: switch back to thread_local Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * arg: switch back to single enum Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * docs: update arg docs Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * chore: fix missing `mlock` from llama_load_mode_from_str + cleanup llama-bench Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * llama: fix mlock not activating Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * arg: add deprecation warning when old and new flags are combined Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * arg: cont add comment for todo in the future Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * docs: sync with upstream Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> * docs: re-sync with upstream again Signed-off-by: Aaron Teo <aaron.teo1@ibm.com> --------- Signed-off-by: Aaron Teo <aaron.teo1@ibm.com>
1 parent da296d6 commit e6dd0e2

20 files changed

Lines changed: 315 additions & 207 deletions

common/arg.cpp

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "common.h"
66
#include "download.h"
77
#include "json-schema-to-grammar.h"
8+
#include "llama.h"
89
#include "log.h"
910
#include "sampling.h"
1011
#include "speculative.h"
@@ -785,6 +786,17 @@ static bool common_params_parse_ex(int argc, char ** argv, common_params_context
785786
arg.c_str(), e.what(), opt.to_string().c_str()));
786787
}
787788
}
789+
790+
// TODO: remove this check after deprecating --mmap|mlock|dio
791+
auto has_arg = [&](std::initializer_list<const char *> names) {
792+
return std::any_of(names.begin(), names.end(), [&](const char * name) {
793+
return seen_args.count(name);
794+
});
795+
};
796+
if (has_arg({"-lm", "--load-mode"}) &&
797+
has_arg({"--mlock", "--mmap", "--no-mmap", "-dio", "--direct-io", "-ndio", "--no-direct-io"})) {
798+
LOG_WRN("DEPRECATED: `--load-mode` and `--mlock`/`--mmap`/`--direct-io` should not be combined; only the last flag on the command line will take effect\n");
799+
}
788800
};
789801

790802
// parse all CLI args now, so that -hf is available below for remote preset resolution
@@ -2495,27 +2507,45 @@ common_params_context common_params_parser_init(common_params & params, llama_ex
24952507
}
24962508
add_opt(common_arg(
24972509
{"--mlock"},
2498-
"force system to keep model in RAM rather than swapping or compressing",
2510+
"DEPRECATED in favor of `--load-mode`: mmap + force system to keep model in RAM rather than swapping or compressing",
24992511
[](common_params & params) {
2500-
params.use_mlock = true;
2512+
LOG_WRN("DEPRECATED: --mlock is deprecated. use --load-mode mlock instead\n");
2513+
params.load_mode = LLAMA_LOAD_MODE_MLOCK;
25012514
}
25022515
).set_env("LLAMA_ARG_MLOCK"));
25032516
add_opt(common_arg(
25042517
{"--mmap"},
25052518
{"--no-mmap"},
2506-
string_format("whether to memory-map model. (if mmap disabled, slower load but may reduce pageouts if not using mlock) (default: %s)", params.use_mmap ? "enabled" : "disabled"),
2519+
"DEPRECATED in favor of `--load-mode`: whether to memory-map model. (if mmap disabled, slower load but may reduce pageouts if not using mlock)",
25072520
[](common_params & params, bool value) {
2508-
params.use_mmap = value;
2521+
LOG_WRN("DEPRECATED: --mmap and --no-mmap are deprecated. use --load-mode mmap instead\n");
2522+
params.load_mode = value ? LLAMA_LOAD_MODE_MMAP : LLAMA_LOAD_MODE_NONE;
25092523
}
25102524
).set_env("LLAMA_ARG_MMAP"));
25112525
add_opt(common_arg(
25122526
{"-dio", "--direct-io"},
25132527
{"-ndio", "--no-direct-io"},
2514-
string_format("use DirectIO if available. (default: %s)", params.use_direct_io ? "enabled" : "disabled"),
2528+
"DEPRECATED in favor of `--load-mode`: use DirectIO if available",
25152529
[](common_params & params, bool value) {
2516-
params.use_direct_io = value;
2530+
LOG_WRN("DEPRECATED: --direct-io and --no-direct-io are deprecated. use --load-mode dio instead\n");
2531+
params.load_mode = value ? LLAMA_LOAD_MODE_DIRECT_IO : LLAMA_LOAD_MODE_NONE;
25172532
}
25182533
).set_env("LLAMA_ARG_DIO"));
2534+
add_opt(common_arg(
2535+
{"-lm", "--load-mode"}, "MODE",
2536+
"model loading mode (default: mmap)\n"
2537+
"- none: no special loading mode\n"
2538+
"- mmap: memory-map model (if mmap disabled, slower load but may reduce pageouts if not using mlock)\n"
2539+
"- mlock: mmap + force system to keep model in RAM rather than swapping or compressing\n"
2540+
"- dio: use DirectIO if available\n",
2541+
[](common_params & params, const std::string & value) {
2542+
/**/ if (value == "none") { params.load_mode = LLAMA_LOAD_MODE_NONE; }
2543+
else if (value == "mmap") { params.load_mode = LLAMA_LOAD_MODE_MMAP; }
2544+
else if (value == "mlock") { params.load_mode = LLAMA_LOAD_MODE_MLOCK; }
2545+
else if (value == "dio") { params.load_mode = LLAMA_LOAD_MODE_DIRECT_IO; }
2546+
else { throw std::invalid_argument("invalid value"); }
2547+
}
2548+
).set_env("LLAMA_ARG_LOAD_MODE"));
25192549
add_opt(common_arg(
25202550
{"--numa"}, "TYPE",
25212551
"attempt optimizations that help on some NUMA systems\n"

common/common.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1558,10 +1558,8 @@ struct llama_model_params common_model_params_to_llama(common_params & params) {
15581558
mparams.n_gpu_layers = params.n_gpu_layers;
15591559
mparams.main_gpu = params.main_gpu;
15601560
mparams.split_mode = params.split_mode;
1561+
mparams.load_mode = params.load_mode;
15611562
mparams.tensor_split = params.tensor_split;
1562-
mparams.use_mmap = params.use_mmap;
1563-
mparams.use_direct_io = params.use_direct_io;
1564-
mparams.use_mlock = params.use_mlock;
15651563
mparams.check_tensors = params.check_tensors;
15661564
mparams.use_extra_bufts = !params.no_extra_bufts;
15671565
mparams.no_host = params.no_host;

common/common.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
#include "ggml-opt.h"
88
#include "ggml.h"
9+
#include "llama.h"
910

1011
#include <set>
1112
#include <sstream>
@@ -482,6 +483,7 @@ struct common_params {
482483
std::vector<size_t> fit_params_target = std::vector<size_t>(llama_max_devices(), 1024 * 1024*1024);
483484

484485
enum llama_split_mode split_mode = LLAMA_SPLIT_MODE_LAYER; // how to split the model across GPUs
486+
enum llama_load_mode load_mode = LLAMA_LOAD_MODE_MMAP; // how to load the model
485487

486488
common_cpu_params cpuparams;
487489
common_cpu_params cpuparams_batch;
@@ -572,9 +574,6 @@ struct common_params {
572574
bool kv_unified = false; // enable unified KV cache
573575

574576
bool input_prefix_bos = false; // prefix BOS to user inputs, preceding input_prefix
575-
bool use_mmap = true; // enable mmap to use filesystem cache
576-
bool use_direct_io = false; // read from disk without buffering
577-
bool use_mlock = false; // use mlock to keep model in memory
578577
bool verbose_prompt = false; // print prompt tokens before generation
579578
bool display_prompt = true; // print prompt before generation
580579
bool no_kv_offload = false; // disable KV offloading

common/fit.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,7 @@ static std::vector<llama_device_memory_data> common_get_device_memory_data_impl(
5454

5555
llama_model_params mparams_copy = *mparams;
5656
mparams_copy.no_alloc = true;
57-
mparams_copy.use_mmap = false;
58-
mparams_copy.use_mlock = false;
57+
mparams_copy.load_mode = LLAMA_LOAD_MODE_NONE;
5958

6059
llama_model * model = llama_model_load_from_file(path_model, mparams_copy);
6160
if (model == nullptr) {

examples/diffusion/diffusion-cli.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,9 +117,7 @@ int main(int argc, char ** argv) {
117117
llama_model_params model_params = llama_model_default_params();
118118
model_params.n_gpu_layers = params.n_gpu_layers;
119119
model_params.devices = params.devices.data();
120-
model_params.use_mmap = params.use_mmap;
121-
model_params.use_direct_io = params.use_direct_io;
122-
model_params.use_mlock = params.use_mlock;
120+
model_params.load_mode = params.load_mode;
123121
model_params.check_tensors = params.check_tensors;
124122

125123
llama_model * model = llama_model_load_from_file(params.model.path.c_str(), model_params);

examples/training/finetune.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,9 @@ int main(int argc, char ** argv) {
2626
return 1;
2727
}
2828

29-
if (params.use_mmap) {
30-
LOG_INF("%s: force disabling memory mapping because it would result in-read-only pointers to the weights\n",
31-
__func__);
32-
params.use_mmap = false;
29+
if (params.load_mode != LLAMA_LOAD_MODE_NONE) {
30+
LOG_INF("%s: forcing load_mode = none to enable writable pointers to the weights\n", __func__);
31+
params.load_mode = LLAMA_LOAD_MODE_NONE;
3332
}
3433
if (params.cache_type_k != GGML_TYPE_F32) {
3534
LOG_INF("%s: force changing k cache type to f32 due to a lack of f16 support for OUT_PROD\n", __func__);

include/llama.h

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,16 @@ extern "C" {
202202
LLAMA_SPLIT_MODE_TENSOR = 3,
203203
};
204204

205+
enum llama_load_mode {
206+
LLAMA_LOAD_MODE_NONE = 0, // no special loading mode
207+
LLAMA_LOAD_MODE_MMAP = 1, // memory map the model
208+
LLAMA_LOAD_MODE_MLOCK = 2, // mmap + force system to keep model in RAM rather than swapping or compressing
209+
LLAMA_LOAD_MODE_DIRECT_IO = 3, // use direct I/O if available
210+
};
211+
212+
LLAMA_API const char * llama_load_mode_name(enum llama_load_mode load_mode);
213+
LLAMA_API enum llama_load_mode llama_load_mode_from_str(const char * str);
214+
205215
enum llama_context_type {
206216
LLAMA_CONTEXT_TYPE_DEFAULT = 0,
207217
LLAMA_CONTEXT_TYPE_MTP = 1,
@@ -301,6 +311,7 @@ extern "C" {
301311

302312
int32_t n_gpu_layers; // number of layers to store in VRAM, a negative value means all layers
303313
enum llama_split_mode split_mode; // how to split the model across multiple GPUs
314+
enum llama_load_mode load_mode; // how to load the model
304315

305316
// the GPU that is used for the entire model when split_mode is LLAMA_SPLIT_MODE_NONE
306317
int32_t main_gpu;
@@ -321,9 +332,6 @@ extern "C" {
321332

322333
// Keep the booleans together to avoid misalignment during copy-by-value.
323334
bool vocab_only; // only load the vocabulary, no weights
324-
bool use_mmap; // use mmap if possible
325-
bool use_direct_io; // use direct io, takes precedence over use_mmap when supported
326-
bool use_mlock; // force system to keep model in RAM
327335
bool check_tensors; // validate model tensor data
328336
bool use_extra_bufts; // use extra buffer types (used for weight repacking)
329337
bool no_host; // bypass host buffer allowing extra buffers to be used

scripts/compare-llama-bench.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
"model_type", "model_size", "model_n_params", "n_batch", "n_ubatch", "n_threads",
2929
"cpu_mask", "cpu_strict", "poll", "type_k", "type_v", "n_gpu_layers",
3030
"split_mode", "main_gpu", "no_kv_offload", "flash_attn", "tensor_split", "tensor_buft_overrides",
31-
"use_mmap", "embeddings", "no_op_offload", "n_prompt", "n_gen", "n_depth",
31+
"load_mode", "embeddings", "no_op_offload", "n_prompt", "n_gen", "n_depth",
3232
"test_time", "avg_ns", "stddev_ns", "avg_ts", "stddev_ts", "n_cpu_moe",
3333
"fit_target", "fit_min_ctx"
3434
]
@@ -38,7 +38,7 @@
3838
"TEXT", "INTEGER", "INTEGER", "INTEGER", "INTEGER", "INTEGER",
3939
"TEXT", "INTEGER", "INTEGER", "TEXT", "TEXT", "INTEGER",
4040
"TEXT", "INTEGER", "INTEGER", "INTEGER", "TEXT", "TEXT",
41-
"INTEGER", "INTEGER", "INTEGER", "INTEGER", "INTEGER", "INTEGER",
41+
"TEXT", "INTEGER", "INTEGER", "INTEGER", "INTEGER", "INTEGER",
4242
"TEXT", "INTEGER", "INTEGER", "REAL", "REAL", "INTEGER",
4343
"INTEGER", "INTEGER"
4444
]
@@ -63,7 +63,7 @@
6363
LLAMA_BENCH_KEY_PROPERTIES = [
6464
"cpu_info", "gpu_info", "backends", "n_gpu_layers", "n_cpu_moe", "tensor_buft_overrides", "model_filename", "model_type",
6565
"n_batch", "n_ubatch", "embeddings", "cpu_mask", "cpu_strict", "poll", "n_threads", "type_k", "type_v",
66-
"use_mmap", "no_kv_offload", "split_mode", "main_gpu", "tensor_split", "flash_attn", "n_prompt", "n_gen", "n_depth",
66+
"load_mode", "no_kv_offload", "split_mode", "main_gpu", "tensor_split", "flash_attn", "n_prompt", "n_gen", "n_depth",
6767
"fit_target", "fit_min_ctx"
6868
]
6969

@@ -73,7 +73,7 @@
7373
]
7474

7575
# Properties that are boolean and are converted to Yes/No for the table:
76-
LLAMA_BENCH_BOOL_PROPERTIES = ["embeddings", "cpu_strict", "use_mmap", "no_kv_offload", "flash_attn"]
76+
LLAMA_BENCH_BOOL_PROPERTIES = ["embeddings", "cpu_strict", "no_kv_offload", "flash_attn"]
7777
TEST_BACKEND_OPS_BOOL_PROPERTIES = ["supported", "passed"]
7878

7979
# Header names for the table (llama-bench):
@@ -82,7 +82,7 @@
8282
"tensor_buft_overrides": "Tensor overrides", "model_filename": "File", "model_type": "Model", "model_size": "Model size [GiB]",
8383
"model_n_params": "Num. of par.", "n_batch": "Batch size", "n_ubatch": "Microbatch size", "embeddings": "Embeddings",
8484
"cpu_mask": "CPU mask", "cpu_strict": "CPU strict", "poll": "Poll", "n_threads": "Threads", "type_k": "K type", "type_v": "V type",
85-
"use_mmap": "Use mmap", "no_kv_offload": "NKVO", "split_mode": "Split mode", "main_gpu": "Main GPU", "tensor_split": "Tensor split",
85+
"load_mode": "Load mode", "no_kv_offload": "NKVO", "split_mode": "Split mode", "main_gpu": "Main GPU", "tensor_split": "Tensor split",
8686
"flash_attn": "FlashAttention",
8787
}
8888

src/llama-model-loader.cpp

Lines changed: 7 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "ggml.h"
55
#include "gguf.h"
66
#include "llama-hparams.h"
7+
#include "llama.h"
78

89
#include <algorithm>
910
#include <array>
@@ -522,8 +523,7 @@ llama_model_loader::llama_model_loader(
522523
const std::string & fname,
523524
std::vector<std::string> & splits,
524525
FILE * file,
525-
bool use_mmap,
526-
bool use_direct_io,
526+
llama_load_mode load_mode,
527527
bool check_tensors,
528528
bool no_alloc,
529529
const llama_model_kv_override * param_overrides_p,
@@ -542,6 +542,9 @@ llama_model_loader::llama_model_loader(
542542

543543
tensor_buft_overrides = param_tensor_buft_overrides_p;
544544

545+
this->use_mmap = load_mode == LLAMA_LOAD_MODE_MMAP || load_mode == LLAMA_LOAD_MODE_MLOCK;
546+
this->use_direct_io = load_mode == LLAMA_LOAD_MODE_DIRECT_IO;
547+
545548
if (!fname.empty()) {
546549
// Load the main GGUF
547550
struct ggml_context * ctx = NULL;
@@ -562,20 +565,6 @@ llama_model_loader::llama_model_loader(
562565
files.emplace_back(new llama_file(fname.c_str(), "rb", use_direct_io));
563566
contexts.emplace_back(ctx);
564567

565-
if (use_mmap && use_direct_io) {
566-
if (files.back()->has_direct_io()) {
567-
LLAMA_LOG_WARN("%s: direct I/O is enabled, disabling mmap\n", __func__);
568-
use_mmap = false;
569-
} else {
570-
LLAMA_LOG_WARN("%s: direct I/O is not available, using mmap\n", __func__);
571-
use_direct_io = false;
572-
573-
// reopen file using std::fopen for mmap
574-
files.pop_back();
575-
files.emplace_back(new llama_file(fname.c_str(), "rb", false));
576-
}
577-
}
578-
579568
// Save tensors data offset of the main file.
580569
// For subsidiary files, `meta` tensor data offset must not be used,
581570
// so we build a unified tensors index for weights.
@@ -816,13 +805,11 @@ llama_model_loader::llama_model_loader(
816805
}
817806
}
818807

819-
if (!llama_mmap::SUPPORTED) {
808+
if (this->use_mmap && !llama_mmap::SUPPORTED) {
820809
LLAMA_LOG_WARN("%s: mmap is not supported on this platform\n", __func__);
821-
use_mmap = false;
810+
this->use_mmap = false;
822811
}
823812

824-
this->use_mmap = use_mmap;
825-
this->use_direct_io = use_direct_io;
826813
this->check_tensors = check_tensors;
827814
this->no_alloc = no_alloc;
828815
}

src/llama-model-loader.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,7 @@ struct llama_model_loader {
126126
const std::string & fname,
127127
std::vector<std::string> & splits, // optional, only need if the split does not follow naming scheme
128128
FILE * file,
129-
bool use_mmap,
130-
bool use_direct_io,
129+
llama_load_mode load_mode,
131130
bool check_tensors,
132131
bool no_alloc,
133132
const llama_model_kv_override * param_overrides_p,

0 commit comments

Comments
 (0)