|
30 | 30 | #include <cassert> |
31 | 31 | #include <cfloat> |
32 | 32 | #include <cstdint> |
| 33 | +#include <cstdlib> |
33 | 34 | #include <cstring> |
34 | 35 | #include <cmath> |
35 | 36 | #include <functional> |
@@ -1251,6 +1252,27 @@ void llama_model_base::load_vocab(llama_model_loader & ml) { |
1251 | 1252 | vocab.load(ml, kv); |
1252 | 1253 | } |
1253 | 1254 |
|
| 1255 | +// WP_RESIDENT_DENSE: when "1", the weight pager keeps DENSE weights VRAM- |
| 1256 | +// resident and pages ONLY routed-expert tensors. Default off. Both the |
| 1257 | +// buffer-allocation filter (is_paged_weight) and the pager-catalog population |
| 1258 | +// MUST use the same routed-expert predicate below, or a tensor left out of |
| 1259 | +// one but not the other ends up never-allocated-never-loaded (garbage). |
| 1260 | +static bool wp_resident_dense_enabled() { |
| 1261 | + const char * v = std::getenv("WP_RESIDENT_DENSE"); |
| 1262 | + return v != nullptr && v[0] == '1'; |
| 1263 | +} |
| 1264 | + |
| 1265 | +// True iff `name` is a consolidated routed-expert tensor |
| 1266 | +// (ffn_{up,gate,down}_exps). Same detection that sets |
| 1267 | +// llama_weight_page_info::is_expert at load. |
| 1268 | +static bool wp_is_routed_expert(const char * name) { |
| 1269 | + const char * p = name ? std::strstr(name, "ffn_") : nullptr; |
| 1270 | + if (p == nullptr) return false; |
| 1271 | + return std::strstr(p, "ffn_up_exps.") != nullptr || |
| 1272 | + std::strstr(p, "ffn_gate_exps.") != nullptr || |
| 1273 | + std::strstr(p, "ffn_down_exps.") != nullptr; |
| 1274 | +} |
| 1275 | + |
1254 | 1276 | bool llama_model_base::load_tensors(llama_model_loader & ml) { |
1255 | 1277 | const auto & split_mode = params.split_mode; |
1256 | 1278 | const auto & use_mlock = params.use_mlock; |
@@ -1612,6 +1634,10 @@ bool llama_model_base::load_tensors(llama_model_loader & ml) { |
1612 | 1634 | if (std::strncmp(n, "output_norm", 11) == 0) return false; |
1613 | 1635 | if (std::strcmp (n, "output.weight") == 0) return false; |
1614 | 1636 | if (ggml_nbytes(t) < WP_MIN_PAGED_BYTES) return false; // tiny -> resident |
| 1637 | + // WP_RESIDENT_DENSE: page ONLY routed experts; every dense |
| 1638 | + // weight becomes resident (allocated by the manual loop below, |
| 1639 | + // loaded by load_all_data). Must match the catalog filter. |
| 1640 | + if (wp_resident_dense_enabled() && !wp_is_routed_expert(n)) return false; |
1615 | 1641 | return true; // it's a paged per-layer weight |
1616 | 1642 | }; |
1617 | 1643 | const bool paging_on_device_buft = |
@@ -1797,10 +1823,18 @@ bool llama_model_base::load_tensors(llama_model_loader & ml) { |
1797 | 1823 | } |
1798 | 1824 | info.is_expert = is_consolidated; |
1799 | 1825 | } |
1800 | | - ml.weight_page_infos.push_back(info); |
1801 | | - // Collect the actual model tensor pointer for the weight pager |
1802 | | - if (weight_pager) { |
1803 | | - weight_pager->weight_tensor_ptrs.push_back(t); |
| 1826 | + // WP_RESIDENT_DENSE: register ONLY routed-expert tensors with |
| 1827 | + // the pager; dense tensors are resident (allocated above by the |
| 1828 | + // manual loop) and must NOT get a pool placeholder. This filter |
| 1829 | + // MUST agree with is_paged_weight() — both use the routed-expert |
| 1830 | + // predicate — or a tensor is never-allocated-never-loaded. |
| 1831 | + const bool page_this = !wp_resident_dense_enabled() || info.is_expert; |
| 1832 | + if (page_this) { |
| 1833 | + ml.weight_page_infos.push_back(info); |
| 1834 | + // Collect the actual model tensor pointer for the weight pager |
| 1835 | + if (weight_pager) { |
| 1836 | + weight_pager->weight_tensor_ptrs.push_back(t); |
| 1837 | + } |
1804 | 1838 | } |
1805 | 1839 | ctx_has_weights = true; |
1806 | 1840 | } |
|
0 commit comments