Add Vulkan longhaul support
This commit is contained in:
+21
-9
@@ -27,9 +27,11 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cinttypes>
|
#include <cinttypes>
|
||||||
#include <climits>
|
#include <climits>
|
||||||
|
#include <cmath>
|
||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <limits>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
#include <set>
|
#include <set>
|
||||||
@@ -56,6 +58,19 @@
|
|||||||
using json = nlohmann::ordered_json;
|
using json = nlohmann::ordered_json;
|
||||||
using namespace common_arg_utils;
|
using namespace common_arg_utils;
|
||||||
|
|
||||||
|
static uint64_t parse_longhaul_cache_gib(const std::string & value) {
|
||||||
|
size_t end = 0;
|
||||||
|
const double gib = std::stod(value, &end);
|
||||||
|
constexpr long double bytes_per_gib = 1024.0L * 1024.0L * 1024.0L;
|
||||||
|
const long double bytes = (long double) gib * bytes_per_gib;
|
||||||
|
|
||||||
|
if (end != value.size() || !std::isfinite(gib) || gib <= 0.0 ||
|
||||||
|
bytes < 1.0L || bytes > (long double) std::numeric_limits<uint64_t>::max()) {
|
||||||
|
throw std::invalid_argument("longhaul cache size must be a positive GiB value");
|
||||||
|
}
|
||||||
|
return (uint64_t) bytes;
|
||||||
|
}
|
||||||
|
|
||||||
static std::initializer_list<enum llama_example> mmproj_examples = {
|
static std::initializer_list<enum llama_example> mmproj_examples = {
|
||||||
LLAMA_EXAMPLE_MTMD,
|
LLAMA_EXAMPLE_MTMD,
|
||||||
LLAMA_EXAMPLE_SERVER,
|
LLAMA_EXAMPLE_SERVER,
|
||||||
@@ -815,7 +830,7 @@ static bool common_params_parse_ex(int argc, char ** argv, common_params_context
|
|||||||
parse_cli_args();
|
parse_cli_args();
|
||||||
|
|
||||||
if (params.load_mode == LLAMA_LOAD_MODE_LONGHAUL && params.longhaul_cache_bytes == 0) {
|
if (params.load_mode == LLAMA_LOAD_MODE_LONGHAUL && params.longhaul_cache_bytes == 0) {
|
||||||
throw std::invalid_argument("error: --longhaul requires --longhaul-cache N\n");
|
throw std::invalid_argument("error: --longhaul requires --longhaul-cache GiB\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
postprocess_cpu_params(params.cpuparams, nullptr);
|
postprocess_cpu_params(params.cpuparams, nullptr);
|
||||||
@@ -2631,19 +2646,16 @@ common_params_context common_params_parser_init(common_params & params, llama_ex
|
|||||||
).set_env("LLAMA_ARG_LOAD_MODE"));
|
).set_env("LLAMA_ARG_LOAD_MODE"));
|
||||||
add_opt(common_arg(
|
add_opt(common_arg(
|
||||||
{"--longhaul"},
|
{"--longhaul"},
|
||||||
"stream routed Qwen3.5 MoE experts through a bounded Metal cache",
|
"stream routed Qwen3.x MoE experts through a bounded GPU cache",
|
||||||
[](common_params & params) {
|
[](common_params & params) {
|
||||||
params.load_mode = LLAMA_LOAD_MODE_LONGHAUL;
|
params.load_mode = LLAMA_LOAD_MODE_LONGHAUL;
|
||||||
}
|
}
|
||||||
).set_env("LLAMA_ARG_LONGHAUL"));
|
).set_env("LLAMA_ARG_LONGHAUL"));
|
||||||
add_opt(common_arg(
|
add_opt(common_arg(
|
||||||
{"--longhaul-cache"}, "N",
|
{"--longhaul-cache"}, "GiB",
|
||||||
"longhaul expert cache size in GiB",
|
"longhaul expert cache size in GiB; decimals are supported",
|
||||||
[](common_params & params, int value) {
|
[](common_params & params, const std::string & value) {
|
||||||
if (value <= 0) {
|
params.longhaul_cache_bytes = parse_longhaul_cache_gib(value);
|
||||||
throw std::invalid_argument("longhaul cache size must be positive");
|
|
||||||
}
|
|
||||||
params.longhaul_cache_bytes = uint64_t(value) * 1024 * 1024 * 1024;
|
|
||||||
}
|
}
|
||||||
).set_env("LLAMA_ARG_LONGHAUL_CACHE"));
|
).set_env("LLAMA_ARG_LONGHAUL_CACHE"));
|
||||||
add_opt(common_arg(
|
add_opt(common_arg(
|
||||||
|
|||||||
+71
-11
@@ -10,11 +10,13 @@ This mode is intended for running a model whose full expert weights do not fit i
|
|||||||
llama-cli \
|
llama-cli \
|
||||||
--model /path/to/model.gguf \
|
--model /path/to/model.gguf \
|
||||||
--longhaul \
|
--longhaul \
|
||||||
--longhaul-cache 2 \
|
--longhaul-cache 0.5 \
|
||||||
--n-gpu-layers 99
|
--n-gpu-layers 99
|
||||||
```
|
```
|
||||||
|
|
||||||
`--longhaul-cache` is the expert cache budget in GiB. It is required when `--longhaul` is used. The same options are accepted by `llama-server`.
|
`--longhaul-cache` is the expert cache budget in GiB and accepts decimal values.
|
||||||
|
It is required when `--longhaul` is used. The same options are accepted by
|
||||||
|
`llama-server`.
|
||||||
|
|
||||||
Longhaul may reduce `--ubatch-size` so that every expert selected by one graph segment can be present in the cache at the same time. The effective value is logged during context creation. If one token selects more experts than the cache has slots, the routed MoE computation is split into multiple stages and the partial results are summed. This permits smaller caches at the cost of additional graph work.
|
Longhaul may reduce `--ubatch-size` so that every expert selected by one graph segment can be present in the cache at the same time. The effective value is logged during context creation. If one token selects more experts than the cache has slots, the routed MoE computation is split into multiple stages and the partial results are summed. This permits smaller caches at the cost of additional graph work.
|
||||||
|
|
||||||
@@ -24,23 +26,81 @@ The normal startup warmup is skipped automatically in longhaul mode. Routed expe
|
|||||||
|
|
||||||
Longhaul currently requires:
|
Longhaul currently requires:
|
||||||
|
|
||||||
- macOS with the Metal backend
|
- macOS with Metal, or Linux with Vulkan
|
||||||
- Qwen3.5 MoE or Laguna architecture
|
- Qwen3.x MoE or Laguna architecture
|
||||||
- all repeating model layers assigned to Metal
|
- all repeating model layers assigned to one supported GPU
|
||||||
- text generation without embeddings or LoRA adapters
|
- text generation without embeddings or LoRA adapters
|
||||||
|
|
||||||
Longhaul does not restrict the GGUF quantization type. Individual tensor types must still be supported by Metal.
|
Longhaul does not restrict the GGUF quantization type. Individual tensor types
|
||||||
|
must still be supported by the selected GPU backend.
|
||||||
|
|
||||||
MTP/speculative decoding, tensor validation during loading, vocabulary-only loading, and CPU or mixed CPU/Metal layer placement are not supported. Both single-file and split GGUF models are supported; routed expert tensors are read from the shard that owns each tensor.
|
MTP/speculative decoding, tensor validation during loading, vocabulary-only
|
||||||
|
loading, multi-GPU placement, and CPU or mixed CPU/GPU layer placement are not
|
||||||
|
supported. Both single-file and split GGUF models are supported; routed expert
|
||||||
|
tensors are read from the shard that owns each tensor.
|
||||||
|
|
||||||
The cache budget covers the compact routed-expert tensors. It does not include dense weights, attention weights, the KV cache, graph allocations, or the temporary buffer used for one expert read. Disk reads bypass the macOS unified file cache where supported, avoiding a second long-lived copy of streamed weights in system RAM.
|
The cache budget covers the compact routed-expert tensors. It does not include
|
||||||
|
dense weights, attention weights, the KV cache, graph allocations, or temporary
|
||||||
|
staging buffers. Disk reads bypass the macOS unified file cache where supported.
|
||||||
|
On Linux, completed streamed reads are released from the kernel page cache. Both
|
||||||
|
avoid a second long-lived copy of streamed weights in system RAM.
|
||||||
|
|
||||||
This implementation synchronizes at each routed MoE layer to discover the selected experts, populate missing cache slots, and continue execution with cache-local expert IDs. Storage speed and expert reuse therefore have a large effect on generation speed.
|
This implementation synchronizes at each routed MoE layer to discover the selected experts, populate missing cache slots, and continue execution with cache-local expert IDs. Storage speed and expert reuse therefore have a large effect on generation speed.
|
||||||
|
|
||||||
Expert IDs are planned as a batch at each synchronization point. Experts already
|
Expert IDs are planned as a batch at each synchronization point. Experts already
|
||||||
needed by that batch are protected from eviction, duplicate IDs are loaded only
|
needed by that batch are protected from eviction, duplicate IDs are loaded only
|
||||||
once, and independent expert slices are read concurrently on shared-memory Metal
|
once, and independent expert slices are read concurrently. Shared host or Metal
|
||||||
devices. Private Metal buffers use a staged fallback.
|
buffers can be populated directly. Private Metal and Vulkan device buffers use
|
||||||
|
staged uploads that are synchronized before routed computation continues.
|
||||||
|
|
||||||
|
## Arch Linux and a 4 GiB GTX 1050 Ti
|
||||||
|
|
||||||
|
Install the Vulkan build dependencies and confirm that the NVIDIA GPU is visible:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
sudo pacman -S --needed base-devel cmake ninja shaderc spirv-headers \
|
||||||
|
vulkan-headers vulkan-icd-loader vulkan-tools
|
||||||
|
vulkaninfo --summary
|
||||||
|
```
|
||||||
|
|
||||||
|
A GTX 10-series card needs a Vulkan driver that still supports Pascal. Driver
|
||||||
|
installation is system-specific; do not continue until `vulkaninfo` lists the
|
||||||
|
GTX 1050 Ti.
|
||||||
|
|
||||||
|
Build Longhaul with Vulkan and list the runtime device names:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cmake -S . -B build-vulkan -G Ninja \
|
||||||
|
-DCMAKE_BUILD_TYPE=Release \
|
||||||
|
-DGGML_VULKAN=ON
|
||||||
|
cmake --build build-vulkan --target llama-cli llama-bench test-longhaul
|
||||||
|
./build-vulkan/bin/llama-cli --list-devices
|
||||||
|
```
|
||||||
|
|
||||||
|
Use the `VulkanN` name corresponding to the discrete NVIDIA card. This matters
|
||||||
|
on systems that also expose an integrated Radeon GPU.
|
||||||
|
|
||||||
|
For `Qwen3.6-35B-A3B-UD-IQ4_XS.gguf`, the non-expert weights use about 2.38 GiB
|
||||||
|
and each cache slot uses about 56.5 MiB. A 0.5 GiB cache provides nine slots for
|
||||||
|
the model's eight selected experts:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
./build-vulkan/bin/llama-cli \
|
||||||
|
--model /path/to/Qwen3.6-35B-A3B-UD-IQ4_XS.gguf \
|
||||||
|
--device VulkanN \
|
||||||
|
--n-gpu-layers 99 \
|
||||||
|
--longhaul \
|
||||||
|
--longhaul-cache 0.5 \
|
||||||
|
--ctx-size 512 \
|
||||||
|
--no-kv-offload \
|
||||||
|
--prompt "Write a short hello message." \
|
||||||
|
--n-predict 32
|
||||||
|
```
|
||||||
|
|
||||||
|
Keep the model on the fastest available drive. A hard drive works correctly,
|
||||||
|
but random expert reads can make generation substantially slower. If Vulkan
|
||||||
|
runs out of memory while the desktop is active, close GPU-heavy applications
|
||||||
|
before reducing the cache below eight slots.
|
||||||
|
|
||||||
## Benchmarking prompt processing
|
## Benchmarking prompt processing
|
||||||
|
|
||||||
@@ -50,7 +110,7 @@ devices. Private Metal buffers use a staged fallback.
|
|||||||
llama-bench \
|
llama-bench \
|
||||||
--model /path/to/model.gguf \
|
--model /path/to/model.gguf \
|
||||||
--load-mode longhaul \
|
--load-mode longhaul \
|
||||||
--longhaul-cache 2 \
|
--longhaul-cache 0.5 \
|
||||||
--n-gpu-layers 99 \
|
--n-gpu-layers 99 \
|
||||||
--n-prompt 2048 \
|
--n-prompt 2048 \
|
||||||
--n-gen 0
|
--n-gen 0
|
||||||
|
|||||||
+66
-40
@@ -89,8 +89,14 @@ void llama_longhaul_cache::io_worker() {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const auto & source = *job->source;
|
const auto & source = *job->source;
|
||||||
void * destination =
|
void * destination = nullptr;
|
||||||
static_cast<uint8_t *>(source.tensor->data) + size_t(job->slot) * source.tensor->nb[2];
|
if (job->direct) {
|
||||||
|
destination =
|
||||||
|
static_cast<uint8_t *>(source.tensor->data) + size_t(job->slot) * source.tensor->nb[2];
|
||||||
|
} else {
|
||||||
|
job->staging.resize(source.expert_size);
|
||||||
|
destination = job->staging.data();
|
||||||
|
}
|
||||||
files.at(source.file_idx)->read_at(
|
files.at(source.file_idx)->read_at(
|
||||||
destination, source.expert_size,
|
destination, source.expert_size,
|
||||||
source.offset + size_t(job->expert_id) * source.expert_size);
|
source.offset + size_t(job->expert_id) * source.expert_size);
|
||||||
@@ -107,20 +113,45 @@ void llama_longhaul_cache::io_worker() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ggml_backend_t llama_longhaul_cache::upload_backend(
|
||||||
|
const llama_model_loader::longhaul_source & source) {
|
||||||
|
ggml_backend_buffer_type_t buft = ggml_backend_buffer_get_type(source.tensor->buffer);
|
||||||
|
ggml_backend_dev_t dev = ggml_backend_buft_get_device(buft);
|
||||||
|
if (dev == nullptr || buft != ggml_backend_dev_buffer_type(dev)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto it = upload_backends.find(dev);
|
||||||
|
if (it != upload_backends.end()) {
|
||||||
|
return it->second.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
ggml_backend_ptr backend(ggml_backend_dev_init(dev, nullptr));
|
||||||
|
if (!backend) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
ggml_backend_t result = backend.get();
|
||||||
|
upload_backends.emplace(dev, std::move(backend));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
bool llama_longhaul_cache::load_plan_sources() {
|
bool llama_longhaul_cache::load_plan_sources() {
|
||||||
const size_t n_direct_sources = std::count_if(
|
const size_t n_jobs = load_plan.size() * sources_by_layer.at(locked_layer).size();
|
||||||
sources_by_layer.at(locked_layer).begin(),
|
|
||||||
sources_by_layer.at(locked_layer).end(),
|
|
||||||
[&](const auto * source) { return source_is_direct(*source); });
|
|
||||||
const size_t n_jobs = load_plan.size() * n_direct_sources;
|
|
||||||
io_jobs.clear();
|
io_jobs.clear();
|
||||||
io_jobs.reserve(n_jobs);
|
io_jobs.reserve(n_jobs);
|
||||||
|
|
||||||
for (const auto & item : load_plan) {
|
for (const auto & item : load_plan) {
|
||||||
for (const auto * source : sources_by_layer.at(locked_layer)) {
|
for (const auto * source : sources_by_layer.at(locked_layer)) {
|
||||||
if (source_is_direct(*source)) {
|
io_jobs.push_back({
|
||||||
io_jobs.push_back({ source, item.first, item.second, false, {} });
|
source,
|
||||||
}
|
item.first,
|
||||||
|
item.second,
|
||||||
|
source_is_direct(*source),
|
||||||
|
{},
|
||||||
|
false,
|
||||||
|
{},
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,35 +164,6 @@ bool llama_longhaul_cache::load_plan_sources() {
|
|||||||
io_ready.notify_all();
|
io_ready.notify_all();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool staged_ok = true;
|
|
||||||
for (const auto & item : load_plan) {
|
|
||||||
const int32_t expert_id = item.first;
|
|
||||||
const int slot = item.second;
|
|
||||||
for (const auto * source : sources_by_layer.at(locked_layer)) {
|
|
||||||
if (source_is_direct(*source)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
read_buffer.resize(source->expert_size);
|
|
||||||
try {
|
|
||||||
files.at(source->file_idx)->read_at(
|
|
||||||
read_buffer.data(), read_buffer.size(),
|
|
||||||
source->offset + size_t(expert_id) * source->expert_size);
|
|
||||||
ggml_backend_tensor_set(
|
|
||||||
source->tensor, read_buffer.data(),
|
|
||||||
size_t(slot) * source->tensor->nb[2], read_buffer.size());
|
|
||||||
bytes_read += read_buffer.size();
|
|
||||||
} catch (const std::exception & e) {
|
|
||||||
last_error = e.what();
|
|
||||||
staged_ok = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!staged_ok) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!io_jobs.empty()) {
|
if (!io_jobs.empty()) {
|
||||||
std::unique_lock<std::mutex> lock(io_mutex);
|
std::unique_lock<std::mutex> lock(io_mutex);
|
||||||
io_done.wait(lock, [&] { return io_pending == 0; });
|
io_done.wait(lock, [&] { return io_pending == 0; });
|
||||||
@@ -174,7 +176,31 @@ bool llama_longhaul_cache::load_plan_sources() {
|
|||||||
}
|
}
|
||||||
bytes_read += job.source->expert_size;
|
bytes_read += job.source->expert_size;
|
||||||
}
|
}
|
||||||
return staged_ok;
|
|
||||||
|
std::vector<ggml_backend_t> pending_backends;
|
||||||
|
for (const auto & job : io_jobs) {
|
||||||
|
if (job.direct) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const size_t offset = size_t(job.slot) * job.source->tensor->nb[2];
|
||||||
|
ggml_backend_t backend = upload_backend(*job.source);
|
||||||
|
if (backend != nullptr) {
|
||||||
|
ggml_backend_tensor_set_async(
|
||||||
|
backend, job.source->tensor, job.staging.data(), offset, job.staging.size());
|
||||||
|
if (std::find(pending_backends.begin(), pending_backends.end(), backend) == pending_backends.end()) {
|
||||||
|
pending_backends.push_back(backend);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ggml_backend_tensor_set(
|
||||||
|
job.source->tensor, job.staging.data(), offset, job.staging.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ggml_backend_t backend : pending_backends) {
|
||||||
|
ggml_backend_synchronize(backend);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void llama_longhaul_cache::invalidate_plan(int layer) {
|
void llama_longhaul_cache::invalidate_plan(int layer) {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -43,6 +44,8 @@ private:
|
|||||||
const llama_model_loader::longhaul_source * source;
|
const llama_model_loader::longhaul_source * source;
|
||||||
int32_t expert_id;
|
int32_t expert_id;
|
||||||
int slot;
|
int slot;
|
||||||
|
bool direct;
|
||||||
|
std::vector<uint8_t> staging;
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
std::string error;
|
std::string error;
|
||||||
};
|
};
|
||||||
@@ -74,7 +77,6 @@ private:
|
|||||||
std::vector<int32_t> available_slots;
|
std::vector<int32_t> available_slots;
|
||||||
std::vector<std::pair<int32_t, int32_t>> load_plan;
|
std::vector<std::pair<int32_t, int32_t>> load_plan;
|
||||||
std::vector<int32_t> id_buffer;
|
std::vector<int32_t> id_buffer;
|
||||||
std::vector<uint8_t> read_buffer;
|
|
||||||
|
|
||||||
std::vector<std::thread> io_workers;
|
std::vector<std::thread> io_workers;
|
||||||
std::vector<io_job> io_jobs;
|
std::vector<io_job> io_jobs;
|
||||||
@@ -85,7 +87,10 @@ private:
|
|||||||
size_t io_pending = 0;
|
size_t io_pending = 0;
|
||||||
bool io_stopping = false;
|
bool io_stopping = false;
|
||||||
|
|
||||||
|
std::map<ggml_backend_dev_t, ggml_backend_ptr> upload_backends;
|
||||||
|
|
||||||
bool source_is_direct(const llama_model_loader::longhaul_source & source) const;
|
bool source_is_direct(const llama_model_loader::longhaul_source & source) const;
|
||||||
|
ggml_backend_t upload_backend(const llama_model_loader::longhaul_source & source);
|
||||||
bool load_plan_sources();
|
bool load_plan_sources();
|
||||||
void invalidate_plan(int layer);
|
void invalidate_plan(int layer);
|
||||||
void io_worker();
|
void io_worker();
|
||||||
|
|||||||
@@ -66,6 +66,8 @@ static std::string llama_format_win_err(DWORD err) {
|
|||||||
// llama_file
|
// llama_file
|
||||||
|
|
||||||
struct llama_file::impl {
|
struct llama_file::impl {
|
||||||
|
bool no_cache = false;
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
HANDLE fp_win32;
|
HANDLE fp_win32;
|
||||||
std::string GetErrorMessageWin32(DWORD error_code) const {
|
std::string GetErrorMessageWin32(DWORD error_code) const {
|
||||||
@@ -448,6 +450,14 @@ void llama_file::read_at(void * ptr, size_t len, size_t offset) {
|
|||||||
}
|
}
|
||||||
n_read += result;
|
n_read += result;
|
||||||
}
|
}
|
||||||
|
#if defined(__linux__) && defined(POSIX_FADV_DONTNEED)
|
||||||
|
if (pimpl->no_cache) {
|
||||||
|
// Longhaul retains useful expert data in its own bounded cache. Drop
|
||||||
|
// completed file reads so the kernel page cache does not become a
|
||||||
|
// second, unbounded copy of the streamed weights.
|
||||||
|
(void) posix_fadvise(file_id(), (off_t) offset, (off_t) len, POSIX_FADV_DONTNEED);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -456,6 +466,12 @@ void llama_file::set_no_cache() const {
|
|||||||
if (fcntl(file_id(), F_NOCACHE, 1) != 0) {
|
if (fcntl(file_id(), F_NOCACHE, 1) != 0) {
|
||||||
throw std::runtime_error(format("failed to disable file cache: %s", strerror(errno)));
|
throw std::runtime_error(format("failed to disable file cache: %s", strerror(errno)));
|
||||||
}
|
}
|
||||||
|
#elif defined(__linux__) && defined(POSIX_FADV_RANDOM)
|
||||||
|
pimpl->no_cache = true;
|
||||||
|
const int err = posix_fadvise(file_id(), 0, 0, POSIX_FADV_RANDOM);
|
||||||
|
if (err != 0) {
|
||||||
|
LLAMA_LOG_WARN("%s: failed to set random-access file advice: %s\n", __func__, strerror(err));
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+12
-6
@@ -1356,9 +1356,6 @@ bool llama_model_base::load_tensors(llama_model_loader & ml) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (params.load_mode == LLAMA_LOAD_MODE_LONGHAUL) {
|
if (params.load_mode == LLAMA_LOAD_MODE_LONGHAUL) {
|
||||||
#if !defined(__APPLE__)
|
|
||||||
throw std::runtime_error("longhaul is only supported on macOS");
|
|
||||||
#endif
|
|
||||||
if (arch != LLM_ARCH_QWEN35MOE && arch != LLM_ARCH_LAGUNA) {
|
if (arch != LLM_ARCH_QWEN35MOE && arch != LLM_ARCH_LAGUNA) {
|
||||||
throw std::runtime_error("longhaul currently requires a qwen35moe or laguna model");
|
throw std::runtime_error("longhaul currently requires a qwen35moe or laguna model");
|
||||||
}
|
}
|
||||||
@@ -1368,12 +1365,21 @@ bool llama_model_base::load_tensors(llama_model_loader & ml) {
|
|||||||
if (params.check_tensors || params.no_alloc || params.vocab_only) {
|
if (params.check_tensors || params.no_alloc || params.vocab_only) {
|
||||||
throw std::runtime_error("longhaul does not support check-tensors, no-alloc, or vocab-only loading");
|
throw std::runtime_error("longhaul does not support check-tensors, no-alloc, or vocab-only loading");
|
||||||
}
|
}
|
||||||
|
ggml_backend_dev_t longhaul_dev = nullptr;
|
||||||
for (int il = 0; il < n_layer_all; ++il) {
|
for (int il = 0; il < n_layer_all; ++il) {
|
||||||
ggml_backend_dev_t dev = pimpl->dev_layer[il].dev;
|
ggml_backend_dev_t dev = pimpl->dev_layer[il].dev;
|
||||||
if (ggml_backend_dev_type(dev) != GGML_BACKEND_DEVICE_TYPE_GPU ||
|
const char * backend = ggml_backend_reg_name(ggml_backend_dev_backend_reg(dev));
|
||||||
strcmp(ggml_backend_reg_name(ggml_backend_dev_backend_reg(dev)), "MTL") != 0) {
|
const bool supported_backend =
|
||||||
throw std::runtime_error("longhaul requires every model layer on Metal");
|
strcmp(backend, "MTL") == 0 || strcmp(backend, "Vulkan") == 0;
|
||||||
|
if (ggml_backend_dev_type(dev) != GGML_BACKEND_DEVICE_TYPE_GPU || !supported_backend) {
|
||||||
|
throw std::runtime_error(
|
||||||
|
"longhaul requires every model layer on a Metal or Vulkan GPU");
|
||||||
}
|
}
|
||||||
|
if (longhaul_dev != nullptr && dev != longhaul_dev) {
|
||||||
|
throw std::runtime_error(
|
||||||
|
"longhaul requires every model layer on one GPU; select it with --device");
|
||||||
|
}
|
||||||
|
longhaul_dev = dev;
|
||||||
}
|
}
|
||||||
ml.configure_longhaul(params.longhaul_cache_bytes, n_expert, n_layer_all);
|
ml.configure_longhaul(params.longhaul_cache_bytes, n_expert, n_layer_all);
|
||||||
if (ml.longhaul_slots < (size_t) n_expert_used) {
|
if (ml.longhaul_slots < (size_t) n_expert_used) {
|
||||||
|
|||||||
@@ -160,6 +160,19 @@ static void test(void) {
|
|||||||
assert(params.load_mode == LLAMA_LOAD_MODE_LONGHAUL);
|
assert(params.load_mode == LLAMA_LOAD_MODE_LONGHAUL);
|
||||||
assert(params.longhaul_cache_bytes == 2ULL * 1024 * 1024 * 1024);
|
assert(params.longhaul_cache_bytes == 2ULL * 1024 * 1024 * 1024);
|
||||||
|
|
||||||
|
argv = {"binary_name", "--longhaul", "--longhaul-cache", "0.5"};
|
||||||
|
assert(true == common_params_parse(argv.size(), list_str_to_char(argv).data(), params, LLAMA_EXAMPLE_COMMON));
|
||||||
|
assert(params.longhaul_cache_bytes == 512ULL * 1024 * 1024);
|
||||||
|
|
||||||
|
argv = {"binary_name", "--longhaul", "--longhaul-cache", "0"};
|
||||||
|
assert(false == common_params_parse(argv.size(), list_str_to_char(argv).data(), params, LLAMA_EXAMPLE_COMMON));
|
||||||
|
|
||||||
|
argv = {"binary_name", "--longhaul", "--longhaul-cache", "nan"};
|
||||||
|
assert(false == common_params_parse(argv.size(), list_str_to_char(argv).data(), params, LLAMA_EXAMPLE_COMMON));
|
||||||
|
|
||||||
|
argv = {"binary_name", "--longhaul", "--longhaul-cache", "0.5GiB"};
|
||||||
|
assert(false == common_params_parse(argv.size(), list_str_to_char(argv).data(), params, LLAMA_EXAMPLE_COMMON));
|
||||||
|
|
||||||
argv = {"binary_name", "--token-cache-size", "256", "--token-cache-dir", "/tmp/llama-token-cache-test.sqlite3"};
|
argv = {"binary_name", "--token-cache-size", "256", "--token-cache-dir", "/tmp/llama-token-cache-test.sqlite3"};
|
||||||
assert(true == common_params_parse(argv.size(), list_str_to_char(argv).data(), params, LLAMA_EXAMPLE_COMMON));
|
assert(true == common_params_parse(argv.size(), list_str_to_char(argv).data(), params, LLAMA_EXAMPLE_COMMON));
|
||||||
assert(params.token_cache_size_mib == 256);
|
assert(params.token_cache_size_mib == 256);
|
||||||
|
|||||||
+30
-2
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include "ggml-backend.h"
|
#include "ggml-backend.h"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -24,12 +25,15 @@ struct longhaul_fixture {
|
|||||||
size_t n_slots,
|
size_t n_slots,
|
||||||
uint32_t n_experts,
|
uint32_t n_experts,
|
||||||
bool two_sources = false,
|
bool two_sources = false,
|
||||||
uint32_t written_experts = 0) {
|
uint32_t written_experts = 0,
|
||||||
|
ggml_backend_dev_t dev = nullptr) {
|
||||||
file = tmpfile();
|
file = tmpfile();
|
||||||
GGML_ASSERT(file != nullptr);
|
GGML_ASSERT(file != nullptr);
|
||||||
write_experts(written_experts == 0 ? n_experts : written_experts, two_sources);
|
write_experts(written_experts == 0 ? n_experts : written_experts, two_sources);
|
||||||
|
|
||||||
backend.reset(ggml_backend_init_by_type(GGML_BACKEND_DEVICE_TYPE_CPU, nullptr));
|
backend.reset(dev
|
||||||
|
? ggml_backend_dev_init(dev, nullptr)
|
||||||
|
: ggml_backend_init_by_type(GGML_BACKEND_DEVICE_TYPE_CPU, nullptr));
|
||||||
GGML_ASSERT(backend);
|
GGML_ASSERT(backend);
|
||||||
|
|
||||||
ggml_init_params params = {
|
ggml_init_params params = {
|
||||||
@@ -152,6 +156,18 @@ static void test_read_failure_recovery(testing & t) {
|
|||||||
t.assert_equal(uint8_t(1), fixture.slot_value(fixture.weights_a, remapped[0]));
|
t.assert_equal(uint8_t(1), fixture.slot_value(fixture.weights_a, remapped[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_staged_device_upload(testing & t, ggml_backend_dev_t dev) {
|
||||||
|
longhaul_fixture fixture(2, 4, true, 0, dev);
|
||||||
|
|
||||||
|
const auto remapped = fixture.remap({3, 1});
|
||||||
|
t.assert_equal(2u, remapped.size());
|
||||||
|
t.assert_equal(uint64_t(4 * longhaul_fixture::expert_size), fixture.cache->bytes_read_count());
|
||||||
|
t.assert_equal(uint8_t(4), fixture.slot_value(fixture.weights_a, remapped[0]));
|
||||||
|
t.assert_equal(uint8_t(36), fixture.slot_value(fixture.weights_b, remapped[0]));
|
||||||
|
t.assert_equal(uint8_t(2), fixture.slot_value(fixture.weights_a, remapped[1]));
|
||||||
|
t.assert_equal(uint8_t(34), fixture.slot_value(fixture.weights_b, remapped[1]));
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char ** argv) {
|
int main(int argc, char ** argv) {
|
||||||
testing t;
|
testing t;
|
||||||
|
|
||||||
@@ -162,6 +178,7 @@ int main(int argc, char ** argv) {
|
|||||||
if (!t.verbose) {
|
if (!t.verbose) {
|
||||||
llama_log_set([](ggml_log_level, const char *, void *) {}, nullptr);
|
llama_log_set([](ggml_log_level, const char *, void *) {}, nullptr);
|
||||||
}
|
}
|
||||||
|
ggml_backend_load_all();
|
||||||
|
|
||||||
if (argc > 1) {
|
if (argc > 1) {
|
||||||
t.set_filter(argv[1]);
|
t.set_filter(argv[1]);
|
||||||
@@ -172,5 +189,16 @@ int main(int argc, char ** argv) {
|
|||||||
t.test("invalid_ids", test_invalid_ids);
|
t.test("invalid_ids", test_invalid_ids);
|
||||||
t.test("read_failure", test_read_failure_recovery);
|
t.test("read_failure", test_read_failure_recovery);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < ggml_backend_dev_count(); ++i) {
|
||||||
|
ggml_backend_dev_t dev = ggml_backend_dev_get(i);
|
||||||
|
const char * backend = ggml_backend_reg_name(ggml_backend_dev_backend_reg(dev));
|
||||||
|
if (strcmp(backend, "Vulkan") == 0) {
|
||||||
|
t.test("vulkan_staged_upload", [dev](testing & current) {
|
||||||
|
test_staged_device_upload(current, dev);
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return t.summary();
|
return t.summary();
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -61,8 +61,8 @@
|
|||||||
| `--mmap, --no-mmap` | DEPRECATED in favor of `--load-mode`: whether to memory-map model. (if mmap disabled, slower load but may reduce pageouts if not using mlock)<br/>(env: LLAMA_ARG_MMAP) |
|
| `--mmap, --no-mmap` | DEPRECATED in favor of `--load-mode`: whether to memory-map model. (if mmap disabled, slower load but may reduce pageouts if not using mlock)<br/>(env: LLAMA_ARG_MMAP) |
|
||||||
| `-dio, --direct-io, -ndio, --no-direct-io` | DEPRECATED in favor of `--load-mode`: use DirectIO if available<br/>(env: LLAMA_ARG_DIO) |
|
| `-dio, --direct-io, -ndio, --no-direct-io` | DEPRECATED in favor of `--load-mode`: use DirectIO if available<br/>(env: LLAMA_ARG_DIO) |
|
||||||
| `-lm, --load-mode MODE` | model loading mode (default: mmap)<br/>- none: no special loading mode<br/>- mmap: memory-map model (if mmap disabled, slower load but may reduce pageouts if not using mlock)<br/>- mlock: force system to keep model in RAM rather than swapping or compressing<br/>- mmap+mlock: mmap + force system to keep model in RAM rather than swapping or compressing<br/>- dio: use DirectIO if available<br/>- longhaul: stream routed MoE experts through a bounded cache<br/><br/>(env: LLAMA_ARG_LOAD_MODE) |
|
| `-lm, --load-mode MODE` | model loading mode (default: mmap)<br/>- none: no special loading mode<br/>- mmap: memory-map model (if mmap disabled, slower load but may reduce pageouts if not using mlock)<br/>- mlock: force system to keep model in RAM rather than swapping or compressing<br/>- mmap+mlock: mmap + force system to keep model in RAM rather than swapping or compressing<br/>- dio: use DirectIO if available<br/>- longhaul: stream routed MoE experts through a bounded cache<br/><br/>(env: LLAMA_ARG_LOAD_MODE) |
|
||||||
| `--longhaul` | stream routed Qwen3.5 MoE experts through a bounded Metal cache<br/>(env: LLAMA_ARG_LONGHAUL) |
|
| `--longhaul` | stream routed Qwen3.x MoE experts through a bounded GPU cache<br/>(env: LLAMA_ARG_LONGHAUL) |
|
||||||
| `--longhaul-cache N` | longhaul expert cache size in GiB<br/>(env: LLAMA_ARG_LONGHAUL_CACHE) |
|
| `--longhaul-cache GiB` | longhaul expert cache size in GiB; decimals are supported<br/>(env: LLAMA_ARG_LONGHAUL_CACHE) |
|
||||||
| `--numa TYPE` | attempt optimizations that help on some NUMA systems<br/>- distribute: spread execution evenly over all nodes<br/>- isolate: only spawn threads on CPUs on the node that execution started on<br/>- numactl: use the CPU map provided by numactl<br/>if run without this previously, it is recommended to drop the system page cache before using this<br/>see https://github.com/ggml-org/llama.cpp/issues/1437<br/>(env: LLAMA_ARG_NUMA) |
|
| `--numa TYPE` | attempt optimizations that help on some NUMA systems<br/>- distribute: spread execution evenly over all nodes<br/>- isolate: only spawn threads on CPUs on the node that execution started on<br/>- numactl: use the CPU map provided by numactl<br/>if run without this previously, it is recommended to drop the system page cache before using this<br/>see https://github.com/ggml-org/llama.cpp/issues/1437<br/>(env: LLAMA_ARG_NUMA) |
|
||||||
| `-dev, --device <dev1,dev2,..>` | comma-separated list of devices to use for offloading (none = don't offload)<br/>use --list-devices to see a list of available devices<br/>(env: LLAMA_ARG_DEVICE) |
|
| `-dev, --device <dev1,dev2,..>` | comma-separated list of devices to use for offloading (none = don't offload)<br/>use --list-devices to see a list of available devices<br/>(env: LLAMA_ARG_DEVICE) |
|
||||||
| `--list-devices` | print list of available devices and exit |
|
| `--list-devices` | print list of available devices and exit |
|
||||||
|
|||||||
@@ -144,8 +144,8 @@ llama-completion.exe -m models\gemma-1.1-7b-it.Q4_K_M.gguf --ignore-eos -n -1
|
|||||||
| `--mmap, --no-mmap` | DEPRECATED in favor of `--load-mode`: whether to memory-map model. (if mmap disabled, slower load but may reduce pageouts if not using mlock)<br/>(env: LLAMA_ARG_MMAP) |
|
| `--mmap, --no-mmap` | DEPRECATED in favor of `--load-mode`: whether to memory-map model. (if mmap disabled, slower load but may reduce pageouts if not using mlock)<br/>(env: LLAMA_ARG_MMAP) |
|
||||||
| `-dio, --direct-io, -ndio, --no-direct-io` | DEPRECATED in favor of `--load-mode`: use DirectIO if available<br/>(env: LLAMA_ARG_DIO) |
|
| `-dio, --direct-io, -ndio, --no-direct-io` | DEPRECATED in favor of `--load-mode`: use DirectIO if available<br/>(env: LLAMA_ARG_DIO) |
|
||||||
| `-lm, --load-mode MODE` | model loading mode (default: mmap)<br/>- none: no special loading mode<br/>- mmap: memory-map model (if mmap disabled, slower load but may reduce pageouts if not using mlock)<br/>- mlock: force system to keep model in RAM rather than swapping or compressing<br/>- mmap+mlock: mmap + force system to keep model in RAM rather than swapping or compressing<br/>- dio: use DirectIO if available<br/>- longhaul: stream routed MoE experts through a bounded cache<br/><br/>(env: LLAMA_ARG_LOAD_MODE) |
|
| `-lm, --load-mode MODE` | model loading mode (default: mmap)<br/>- none: no special loading mode<br/>- mmap: memory-map model (if mmap disabled, slower load but may reduce pageouts if not using mlock)<br/>- mlock: force system to keep model in RAM rather than swapping or compressing<br/>- mmap+mlock: mmap + force system to keep model in RAM rather than swapping or compressing<br/>- dio: use DirectIO if available<br/>- longhaul: stream routed MoE experts through a bounded cache<br/><br/>(env: LLAMA_ARG_LOAD_MODE) |
|
||||||
| `--longhaul` | stream routed Qwen3.5 MoE experts through a bounded Metal cache<br/>(env: LLAMA_ARG_LONGHAUL) |
|
| `--longhaul` | stream routed Qwen3.x MoE experts through a bounded GPU cache<br/>(env: LLAMA_ARG_LONGHAUL) |
|
||||||
| `--longhaul-cache N` | longhaul expert cache size in GiB<br/>(env: LLAMA_ARG_LONGHAUL_CACHE) |
|
| `--longhaul-cache GiB` | longhaul expert cache size in GiB; decimals are supported<br/>(env: LLAMA_ARG_LONGHAUL_CACHE) |
|
||||||
| `--numa TYPE` | attempt optimizations that help on some NUMA systems<br/>- distribute: spread execution evenly over all nodes<br/>- isolate: only spawn threads on CPUs on the node that execution started on<br/>- numactl: use the CPU map provided by numactl<br/>if run without this previously, it is recommended to drop the system page cache before using this<br/>see https://github.com/ggml-org/llama.cpp/issues/1437<br/>(env: LLAMA_ARG_NUMA) |
|
| `--numa TYPE` | attempt optimizations that help on some NUMA systems<br/>- distribute: spread execution evenly over all nodes<br/>- isolate: only spawn threads on CPUs on the node that execution started on<br/>- numactl: use the CPU map provided by numactl<br/>if run without this previously, it is recommended to drop the system page cache before using this<br/>see https://github.com/ggml-org/llama.cpp/issues/1437<br/>(env: LLAMA_ARG_NUMA) |
|
||||||
| `-dev, --device <dev1,dev2,..>` | comma-separated list of devices to use for offloading (none = don't offload)<br/>use --list-devices to see a list of available devices<br/>(env: LLAMA_ARG_DEVICE) |
|
| `-dev, --device <dev1,dev2,..>` | comma-separated list of devices to use for offloading (none = don't offload)<br/>use --list-devices to see a list of available devices<br/>(env: LLAMA_ARG_DEVICE) |
|
||||||
| `--list-devices` | print list of available devices and exit |
|
| `--list-devices` | print list of available devices and exit |
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ test parameters:
|
|||||||
-ub, --ubatch-size <n> (default: 512)
|
-ub, --ubatch-size <n> (default: 512)
|
||||||
-ctk, --cache-type-k <t> (default: f16)
|
-ctk, --cache-type-k <t> (default: f16)
|
||||||
-ctv, --cache-type-v <t> (default: f16)
|
-ctv, --cache-type-v <t> (default: f16)
|
||||||
--longhaul-cache <GiB> expert cache size for longhaul mode
|
--longhaul-cache <GiB> expert cache size for longhaul mode (decimals supported)
|
||||||
-t, --threads <n> (default: system dependent)
|
-t, --threads <n> (default: system dependent)
|
||||||
-C, --cpu-mask <hex,hex> (default: 0x0)
|
-C, --cpu-mask <hex,hex> (default: 0x0)
|
||||||
--cpu-strict <0|1> (default: 0)
|
--cpu-strict <0|1> (default: 0)
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
#include <limits>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
@@ -37,6 +38,20 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// utils
|
// utils
|
||||||
|
static uint64_t parse_longhaul_cache_gib(const char * value) {
|
||||||
|
size_t end = 0;
|
||||||
|
const std::string text(value);
|
||||||
|
const double gib = std::stod(text, &end);
|
||||||
|
constexpr long double bytes_per_gib = 1024.0L * 1024.0L * 1024.0L;
|
||||||
|
const long double bytes = (long double) gib * bytes_per_gib;
|
||||||
|
|
||||||
|
if (end != text.size() || !std::isfinite(gib) || gib <= 0.0 ||
|
||||||
|
bytes < 1.0L || bytes > (long double) std::numeric_limits<uint64_t>::max()) {
|
||||||
|
throw std::invalid_argument("invalid longhaul cache size");
|
||||||
|
}
|
||||||
|
return (uint64_t) bytes;
|
||||||
|
}
|
||||||
|
|
||||||
static uint64_t get_time_ns() {
|
static uint64_t get_time_ns() {
|
||||||
using clock = std::chrono::high_resolution_clock;
|
using clock = std::chrono::high_resolution_clock;
|
||||||
return std::chrono::nanoseconds(clock::now().time_since_epoch()).count();
|
return std::chrono::nanoseconds(clock::now().time_since_epoch()).count();
|
||||||
@@ -462,7 +477,7 @@ static void print_usage(int /* argc */, char ** argv) {
|
|||||||
printf(" -fa, --flash-attn <on|off|auto> (default: %s)\n", join(transform_to_str(cmd_params_defaults.flash_attn, llama_flash_attn_type_name), ",").c_str());
|
printf(" -fa, --flash-attn <on|off|auto> (default: %s)\n", join(transform_to_str(cmd_params_defaults.flash_attn, llama_flash_attn_type_name), ",").c_str());
|
||||||
printf(" -dev, --device <dev0/dev1/...> (default: auto)\n");
|
printf(" -dev, --device <dev0/dev1/...> (default: auto)\n");
|
||||||
printf(" -lm, --load-mode <none|mmap|mlock|mmap+mlock|dio|longhaul> (default: %s)\n", join(transform_to_str(cmd_params_defaults.load_mode, llama_load_mode_name), ",").c_str());
|
printf(" -lm, --load-mode <none|mmap|mlock|mmap+mlock|dio|longhaul> (default: %s)\n", join(transform_to_str(cmd_params_defaults.load_mode, llama_load_mode_name), ",").c_str());
|
||||||
printf(" --longhaul-cache <GiB> expert cache size for longhaul mode\n");
|
printf(" --longhaul-cache <GiB> expert cache size for longhaul mode (decimals supported)\n");
|
||||||
printf(" -mmp, --mmap <0|1> (DEPRECATED IN FAVOUR OF --load-mode)\n");
|
printf(" -mmp, --mmap <0|1> (DEPRECATED IN FAVOUR OF --load-mode)\n");
|
||||||
printf(" -dio, --direct-io <0|1> (DEPRECATED IN FAVOUR OF --load-mode)\n");
|
printf(" -dio, --direct-io <0|1> (DEPRECATED IN FAVOUR OF --load-mode)\n");
|
||||||
printf(" -embd, --embeddings <0|1> (default: %s)\n", join(cmd_params_defaults.embeddings, ",").c_str());
|
printf(" -embd, --embeddings <0|1> (default: %s)\n", join(cmd_params_defaults.embeddings, ",").c_str());
|
||||||
@@ -795,12 +810,12 @@ static cmd_params parse_cmd_params(int argc, char ** argv) {
|
|||||||
invalid_param = true;
|
invalid_param = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
const uint64_t gib = std::stoull(argv[i]);
|
try {
|
||||||
if (gib == 0 || gib > UINT64_MAX / 1024 / 1024 / 1024) {
|
params.longhaul_cache_bytes = parse_longhaul_cache_gib(argv[i]);
|
||||||
|
} catch (const std::exception &) {
|
||||||
invalid_param = true;
|
invalid_param = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
params.longhaul_cache_bytes = gib * 1024 * 1024 * 1024;
|
|
||||||
} else if (arg == "-mg" || arg == "--main-gpu") {
|
} else if (arg == "-mg" || arg == "--main-gpu") {
|
||||||
if (++i >= argc) {
|
if (++i >= argc) {
|
||||||
invalid_param = true;
|
invalid_param = true;
|
||||||
@@ -1154,7 +1169,7 @@ static cmd_params parse_cmd_params(int argc, char ** argv) {
|
|||||||
}
|
}
|
||||||
if (std::find(params.load_mode.begin(), params.load_mode.end(), LLAMA_LOAD_MODE_LONGHAUL) != params.load_mode.end() &&
|
if (std::find(params.load_mode.begin(), params.load_mode.end(), LLAMA_LOAD_MODE_LONGHAUL) != params.load_mode.end() &&
|
||||||
params.longhaul_cache_bytes == 0) {
|
params.longhaul_cache_bytes == 0) {
|
||||||
fprintf(stderr, "error: longhaul load mode requires --longhaul-cache N\n");
|
fprintf(stderr, "error: longhaul load mode requires --longhaul-cache GiB\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
if (params.main_gpu.empty()) {
|
if (params.main_gpu.empty()) {
|
||||||
|
|||||||
@@ -78,8 +78,8 @@ For the full list of features, please refer to [server's changelog](https://gith
|
|||||||
| `--mmap, --no-mmap` | DEPRECATED in favor of `--load-mode`: whether to memory-map model. (if mmap disabled, slower load but may reduce pageouts if not using mlock)<br/>(env: LLAMA_ARG_MMAP) |
|
| `--mmap, --no-mmap` | DEPRECATED in favor of `--load-mode`: whether to memory-map model. (if mmap disabled, slower load but may reduce pageouts if not using mlock)<br/>(env: LLAMA_ARG_MMAP) |
|
||||||
| `-dio, --direct-io, -ndio, --no-direct-io` | DEPRECATED in favor of `--load-mode`: use DirectIO if available<br/>(env: LLAMA_ARG_DIO) |
|
| `-dio, --direct-io, -ndio, --no-direct-io` | DEPRECATED in favor of `--load-mode`: use DirectIO if available<br/>(env: LLAMA_ARG_DIO) |
|
||||||
| `-lm, --load-mode MODE` | model loading mode (default: mmap)<br/>- none: no special loading mode<br/>- mmap: memory-map model (if mmap disabled, slower load but may reduce pageouts if not using mlock)<br/>- mlock: force system to keep model in RAM rather than swapping or compressing<br/>- mmap+mlock: mmap + force system to keep model in RAM rather than swapping or compressing<br/>- dio: use DirectIO if available<br/>- longhaul: stream routed MoE experts through a bounded cache<br/><br/>(env: LLAMA_ARG_LOAD_MODE) |
|
| `-lm, --load-mode MODE` | model loading mode (default: mmap)<br/>- none: no special loading mode<br/>- mmap: memory-map model (if mmap disabled, slower load but may reduce pageouts if not using mlock)<br/>- mlock: force system to keep model in RAM rather than swapping or compressing<br/>- mmap+mlock: mmap + force system to keep model in RAM rather than swapping or compressing<br/>- dio: use DirectIO if available<br/>- longhaul: stream routed MoE experts through a bounded cache<br/><br/>(env: LLAMA_ARG_LOAD_MODE) |
|
||||||
| `--longhaul` | stream routed Qwen3.5 MoE experts through a bounded Metal cache<br/>(env: LLAMA_ARG_LONGHAUL) |
|
| `--longhaul` | stream routed Qwen3.x MoE experts through a bounded GPU cache<br/>(env: LLAMA_ARG_LONGHAUL) |
|
||||||
| `--longhaul-cache N` | longhaul expert cache size in GiB<br/>(env: LLAMA_ARG_LONGHAUL_CACHE) |
|
| `--longhaul-cache GiB` | longhaul expert cache size in GiB; decimals are supported<br/>(env: LLAMA_ARG_LONGHAUL_CACHE) |
|
||||||
| `--numa TYPE` | attempt optimizations that help on some NUMA systems<br/>- distribute: spread execution evenly over all nodes<br/>- isolate: only spawn threads on CPUs on the node that execution started on<br/>- numactl: use the CPU map provided by numactl<br/>if run without this previously, it is recommended to drop the system page cache before using this<br/>see https://github.com/ggml-org/llama.cpp/issues/1437<br/>(env: LLAMA_ARG_NUMA) |
|
| `--numa TYPE` | attempt optimizations that help on some NUMA systems<br/>- distribute: spread execution evenly over all nodes<br/>- isolate: only spawn threads on CPUs on the node that execution started on<br/>- numactl: use the CPU map provided by numactl<br/>if run without this previously, it is recommended to drop the system page cache before using this<br/>see https://github.com/ggml-org/llama.cpp/issues/1437<br/>(env: LLAMA_ARG_NUMA) |
|
||||||
| `-dev, --device <dev1,dev2,..>` | comma-separated list of devices to use for offloading (none = don't offload)<br/>use --list-devices to see a list of available devices<br/>(env: LLAMA_ARG_DEVICE) |
|
| `-dev, --device <dev1,dev2,..>` | comma-separated list of devices to use for offloading (none = don't offload)<br/>use --list-devices to see a list of available devices<br/>(env: LLAMA_ARG_DEVICE) |
|
||||||
| `--list-devices` | print list of available devices and exit |
|
| `--list-devices` | print list of available devices and exit |
|
||||||
|
|||||||
Reference in New Issue
Block a user