@@ -1692,6 +1692,37 @@ static void ds4_gpu_model_views_clear(void) {
16921692 g_model_view_count = 0;
16931693}
16941694
1695+ /* Replace one model's view set without discarding auxiliary GGUF mappings.
1696+ * DeepSeek V4 vision keeps its encoder in a separate mmap. SSD streaming
1697+ * remaps receiver spans between prefill stages, so clearing the global view
1698+ * table here would also unmap the vision encoder before visual routing. */
1699+ static void ds4_gpu_model_views_remove_map(
1700+ const void *model_map,
1701+ uint64_t model_size) {
1702+ uint32_t out = 0;
1703+ for (uint32_t i = 0; i < g_model_view_count; i++) {
1704+ if (g_model_views[i].model_map == model_map &&
1705+ g_model_views[i].model_size == model_size) {
1706+ g_model_views[i].buffer = nil;
1707+ g_model_views[i].model_map = NULL;
1708+ g_model_views[i].model_size = 0;
1709+ g_model_views[i].model_offset = 0;
1710+ g_model_views[i].bytes = 0;
1711+ continue;
1712+ }
1713+ if (out != i) g_model_views[out] = g_model_views[i];
1714+ out++;
1715+ }
1716+ for (uint32_t i = out; i < g_model_view_count; i++) {
1717+ g_model_views[i].buffer = nil;
1718+ g_model_views[i].model_map = NULL;
1719+ g_model_views[i].model_size = 0;
1720+ g_model_views[i].model_offset = 0;
1721+ g_model_views[i].bytes = 0;
1722+ }
1723+ g_model_view_count = out;
1724+ }
1725+
16951726static void ds4_gpu_model_residency_clear(void) {
16961727#if TARGET_OS_OSX
16971728 if (@available(macOS 15.0, *)) {
@@ -11364,15 +11395,15 @@ int ds4_gpu_set_model_map_spans(
1136411395 max_tensor_bytes = ds4_gpu_effective_model_max_tensor_bytes(model_size, max_tensor_bytes);
1136511396
1136611397 ds4_gpu_model_residency_clear();
11367- ds4_gpu_model_views_clear( );
11398+ ds4_gpu_model_views_remove_map(model_map, model_size );
1136811399
1136911400 uint64_t mapped_total = 0;
1137011401 uint64_t first_offset = UINT64_MAX;
1137111402 for (uint32_t i = 0; i < count; i++) {
1137211403 if (offsets[i] > model_size || sizes[i] == 0 || sizes[i] > model_size - offsets[i]) {
1137311404 fprintf(stderr, "ds4: Metal model span %u is outside the GGUF mapping\n", i);
1137411405 ds4_gpu_model_residency_clear();
11375- ds4_gpu_model_views_clear( );
11406+ ds4_gpu_model_views_remove_map(model_map, model_size );
1137611407 return 0;
1137711408 }
1137811409 if (offsets[i] < first_offset) first_offset = offsets[i];
@@ -11386,13 +11417,13 @@ int ds4_gpu_set_model_map_spans(
1138611417 true,
1138711418 &mapped_total)) {
1138811419 ds4_gpu_model_residency_clear();
11389- ds4_gpu_model_views_clear( );
11420+ ds4_gpu_model_views_remove_map(model_map, model_size );
1139011421 return 0;
1139111422 }
1139211423 }
1139311424 if (!ds4_gpu_finish_model_views(t0, mapped_total, first_offset)) {
1139411425 ds4_gpu_model_residency_clear();
11395- ds4_gpu_model_views_clear( );
11426+ ds4_gpu_model_views_remove_map(model_map, model_size );
1139611427 return 0;
1139711428 }
1139811429 g_model_map_ptr = model_map;
0 commit comments