dsv41: the layer-major (chunked) prompt is the default on every run: chunks of 1024 for the single-card default run, staging ring 16 MB where the cards hold most of the experts

This commit is contained in:
Niko1221 committed 2026-10-23 19:59:13 +02:00
1 parent 41856f6594
commit fb321d62cb
1 file changed
+7 -6
+7 -6
View File
@@ -791,7 +791,7 @@ struct Model::Impl {
unsigned win_seq = 0; // the windows the threads ran (the hand-offs' seq)
// the chunked prompt path (threads mode): chunk tokens a pass, runs shorter than chunk_min in windows
int chunk = 0, chunk_min = 512;
static constexpr bool kChunkedPromptDefault = false; // flip once the chunk buffers are elastic (decode unchanged)
static constexpr bool kChunkedPromptDefault = true; // the layer-major prompt is the default (gate: KL 0.1685 vs 0.1686, 8K prompt 6x, decode within 2% - ds4 notes-dsv41-r97)
static constexpr int kFlowChunkMin = 2; // chunk_min with every device's layers on the flow (see load)
// --prefill-chunk at most (route() runs in kVlRows-row slabs). The default stays kVlRows: a 16384-token chunk
// reads a 16K prompt's experts once instead of twice (V100: 461.8 -> 321.3 s, 736 -> 506 GB read) but its buffers
@@ -1880,7 +1880,8 @@ struct Model::Impl {
o.vram_experts;
file_experts = exp_b - std::max(0.0, room - other_b) + (double) kRamMargin > (double) ram_avail();
}
chunk = prompt_par ? (o.prefill_chunk >= 0 ? o.prefill_chunk : file_experts ? kVlRows : 2048) : 0;
const bool own_default = !(par || o.tp > 1); // (the single-card default run the chunked path newly takes: chunks of 1024 - 8K prompt 370 tok/s on 4 x R9700, 214 at 8192; the threads / tp runs keep theirs)
chunk = prompt_par ? (o.prefill_chunk >= 0 ? o.prefill_chunk : own_default ? 1024 : file_experts ? kVlRows : 2048) : 0;
const char* dc = std::getenv("DS4_CHUNK"); // (tests: down to 16, a short prompt in several chunks)
if (dc != nullptr) chunk = prompt_par ? std::atoi(dc) : 0;
if (const char* v = std::getenv("DS4_CHUNK_MIN")) chunk_min = std::max(1, std::atoi(v));
@@ -2668,7 +2669,7 @@ struct Model::Impl {
}
// the staging ring's size (MB) for the experts a chunk streams from the CPU lane: 400 where a good part of them are
// streamed; 64 where the cards hold most of the experts (they are within 30% of fitting) (a 4-card box) - the ring's VRAM is then worth more
// streamed; 16 where the cards hold most of the experts (they are within 30% of fitting) (a 4-card box) - the ring's VRAM is then worth more
// as expert slots, and the decode after a prompt keeps the windowed path's speed (R9700 x4: 29.6 -> 31.7 tok/s)
size_t ring_mb_auto() const {
double exp_b = 0, other_b = 0, room = 0;
@@ -2681,11 +2682,11 @@ struct Model::Impl {
}
for (const Dev& d : devs)
room += std::max(0.0, (double) d.free0 - (double) ((size_t) o.reserve_mib << 20) - 1.5 * (1 << 30)) * o.vram_experts;
const bool fit = exp_b > 0 && exp_b <= 1.3 * std::max(1.0, room - other_b); // (the cards hold most of them: R9700 x4 1.16, 2 x 3090 ~3, one card 5+)
const bool fit = exp_b > 0 && exp_b <= 1.3 * std::max(1.0, room - other_b); // (R9700 x4: 1.16 -> ring 16: decode -1.8% after a prompt, 64: -4.4%, 400: -4.6%)
if (o.verbose)
std::fprintf(stderr, "ds4: staging ring: experts %.1f GB, VRAM room %.1f GB, dense %.1f GB -> %d MB\n", exp_b / 1e9,
room / 1e9, other_b / 1e9, fit ? 64 : 400);
return fit ? 64 : 400;
room / 1e9, other_b / 1e9, fit ? 16 : 400);
return fit ? 16 : 400;
}
bool alloc_chunks(std::string& err) {
chunks.resize(devs.size());