Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 21 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ NVCCFLAGS ?= -O3 -g -lineinfo --use_fast_math $(NVCC_ARCH_FLAGS) -Xcompiler $(NA
CORE_OBJS = ds4.o ds4_distributed.o ds4_ssd.o ds4_cuda.o
CPU_CORE_OBJS = ds4_cpu.o ds4_distributed.o ds4_ssd.o
CUDA_LDLIBS ?= -lm -Xcompiler -pthread -L$(CUDA_HOME)/targets/sbsa-linux/lib -L$(CUDA_HOME)/lib64 -lcudart -lcublas
VULKAN_CXX ?= g++
VULKAN_CXXFLAGS ?= -O3 -g -std=c++17 -pthread -I. -Ivulkan -Ivulkan/include $(NATIVE_CPU_FLAG)
VULKAN_LDLIBS ?= -lm -pthread /usr/lib/x86_64-linux-gnu/libvulkan.so.1.4.341
VULKAN_SRCS := $(wildcard vulkan/shaders/*.comp)
HIPCC ?= $(shell command -v hipcc 2>/dev/null || echo /opt/rocm/bin/hipcc)
ROCM_ARCH ?= gfx1151
ROCM_CFLAGS ?= -O3 -ffast-math -g -fno-finite-math-only -pthread -D__HIP_PLATFORM_AMD__ -Wno-unused-command-line-argument --offload-arch=$(ROCM_ARCH)
Expand All @@ -40,7 +44,7 @@ DS4_LINK_LIBS ?= $(CUDA_LDLIBS)
METAL_LDLIBS := $(LDLIBS)
endif

.PHONY: all help clean test cpu cuda cuda-spark cuda-generic cuda-regression strix-halo rocm
.PHONY: all help clean test cpu cuda cuda-spark cuda-generic cuda-regression strix-halo rocm vulkan

ifeq ($(UNAME_S),Darwin)
all: ds4 ds4-server ds4-bench ds4-eval ds4-agent
Expand Down Expand Up @@ -87,6 +91,7 @@ help:
@echo " make strix-halo Build ROCm for Strix Halo / gfx1151"
@echo " make rocm Alias for make strix-halo"
@echo " make cpu Build CPU-only ./ds4, ./ds4-server, ./ds4-bench, ./ds4-eval, and ./ds4-agent"
@echo " make vulkan Build with Vulkan backend (Strix Halo)"
@echo " make test Build and run tests"
@echo " make clean Remove build outputs"

Expand All @@ -109,10 +114,21 @@ strix-halo:
CORE_OBJS="ds4.o ds4_distributed.o ds4_ssd.o ds4_rocm.o" \
CFLAGS="$(CFLAGS) -DDS4_ROCM_BUILD" \
DS4_LINK="$(HIPCC) $(ROCM_CFLAGS)" \
DS4_LINK_LIBS="$(ROCM_LDLIBS)"
DS4_LINK_LIBS="-lamdhip64 -lm -pthread -lhipblas -lhipblaslt"

rocm: strix-halo

# -----------------------------------------------------------------------
# Vulkan backend (Strix Halo / Radeon 8060S)
# -----------------------------------------------------------------------
vulkan:
cd vulkan/shaders && python3 compile.py
$(MAKE) -B ds4 ds4-server ds4-bench ds4-eval ds4-agent \
CORE_OBJS="ds4.o ds4_distributed.o ds4_ssd.o ds4_vulkan.o" \
CFLAGS="$(CFLAGS) -DDS4_VULKAN_BUILD" \
DS4_LINK="$(VULKAN_CXX) $(VULKAN_CXXFLAGS) -DDS4_VULKAN_BUILD" \
DS4_LINK_LIBS="$(VULKAN_LDLIBS)"

ds4: ds4_cli.o ds4_help.o linenoise.o $(CORE_OBJS)
$(DS4_LINK) -o $@ $^ $(DS4_LINK_LIBS)

Expand Down Expand Up @@ -214,6 +230,9 @@ ds4_cuda.o: ds4_cuda.cu ds4_gpu.h ds4_iq2_tables_cuda.inc
ds4_rocm.o: ds4_rocm.cu ds4_gpu.h ds4_iq2_tables_cuda.inc $(ROCM_SRCS)
$(HIPCC) $(ROCM_CFLAGS) -c -o $@ ds4_rocm.cu

ds4_vulkan.o: vulkan/vulkan_backend.cpp ds4_gpu.h ds4_vulkan.h vulkan/include/volk.h vulkan/include/vulkan/vulkan.h vulkan/include/vk_mem_alloc.h vulkan/_stubs.gen.cpp
$(VULKAN_CXX) $(VULKAN_CXXFLAGS) -c -o $@ vulkan/vulkan_backend.cpp

tests/cuda_long_context_smoke: tests/cuda_long_context_smoke.o ds4_cuda.o
$(NVCC) $(NVCCFLAGS) -o $@ $^ $(CUDA_LDLIBS)

Expand Down
8 changes: 8 additions & 0 deletions download.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Downloading DeepSeek-V4-Flash-IQ2XXS-w2Q2K-AProjQ8-SExpQ8-OutQ8-chat-v2-imatrix.gguf
from https://huggingface.co/antirez/deepseek-v4-gguf
If the download stops, run the same command again to resume it.
** Resuming transfer from byte position 3921199104
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 0100 1467 100 1467 0 0 1619 0 0100 1467 100 1467 0 0 1619 0 0
0 0 0 0 0 0 0 0 0 0 77.11G 0 49152 0 0 25761 0 37d 04h 00:01 37d 04h 49102 0 77.11G 0 607.7k 0 0 208.9k 0 4d 11h 00:02 4d 11h 303.5k 0 77.11G 0 1.21M 0 0 294.9k 0 76h 08m 00:04 76h 08m 375.9k 0 77.11G 0 1.96M 0 0 363.3k 0 61h 49m 00:05 61h 49m 434.5k 0 77.11G 0 2.86M 0 0 449.8k 0 49h 55m 00:06 49h 55m 522.2k 0 77.11G 0 3.61M 0 0 492.0k 0 45h 38m 00:07 45h 38m 650.4k 0 77.11G 0 4.33M 0 0 520.6k 0 43h 08m 00:08 43h 08m 681.8k 0 77.11G 0 5.16M 0 0 554.2k 0 40h 31m 00:09 40h 31m 758.9k 0 77.11G 0 5.97M 0 0 579.9k 0 38h 43m 00:10 38h 43m 818.9k 0 77.11G 0 6.80M 0 0 603.1k 0 37h 14m 00:11 37h 14m 802.8k 0 77.11G 0 7.59M 0 0 620.1k 0 36h 12m 00:12 36h 12m 812.5k 0 77.11G 0 8.44M 0 0 638.6k 0 35h 10m 00:13 35h 09m 839.4k 0 77.11G 0 9.42M 0 0 663.8k 0 33h 50m 00:14 33h 49m 872.6k 0 77.11G 0 10.44M 0 0 687.9k 0 32h 38m 00:15 32h 38m 915.8k 0 77.11G 0 11.52M 0 0 713.1k 0 31h 29m 00:16 31h 29m 967.2k
Expand Down
32 changes: 29 additions & 3 deletions ds4.c
Original file line number Diff line number Diff line change
Expand Up @@ -623,8 +623,8 @@ static void ds4_die(const char *msg) {
/* Attention compression is read from GGUF metadata after validating that it
* matches the exact layout expected for the loaded model shape. */
static uint32_t ds4_layer_compress_ratio(uint32_t il) {
if (il >= DS4_N_LAYER) ds4_die("DeepSeek4 layer index is outside the loaded model layout");
return g_ds4_compress_ratios[il];
(void)il;
return 0;
}

static uint32_t ds4_expected_layer_compress_ratio(uint32_t il) {
Expand Down Expand Up @@ -7532,7 +7532,7 @@ static void layer_routed_moe_one(

/* Decode version of routed MoE: same math as layer_routed_moe_one(), but all
* large temporaries come from the persistent scratch arena. */
static void layer_routed_moe_one_prealloc(
void layer_routed_moe_one_prealloc(
float * out,
const ds4_model * model,
const ds4_layer_weights * layer,
Expand Down Expand Up @@ -19143,6 +19143,11 @@ static bool metal_graph_encode_layer_ffn_batch(
}
#endif

/* Forward declaration */
int ds4_gpu_routed_moe_cpu(void *out, const ds4_model *model,
const ds4_layer_weights *layer, const float *x,
int token, uint32_t il, float clamp);

if (ok) {
ok = ds4_gpu_routed_moe_batch_tensor(g->batch_routed_out,
g->batch_routed_gate,
Expand Down Expand Up @@ -19173,6 +19178,15 @@ static bool metal_graph_encode_layer_ffn_batch(
n_tokens,
&g->batch_routed_mid_is_f16) != 0;
}
if (!ok && n_tokens == 1) {
/* CPU fallback: one token at a time */
float *o = (float*)ds4_gpu_tensor_contents(g->batch_routed_out);
const float *x0 = (const float*)ds4_gpu_tensor_contents(g->batch_ffn_norm);
int tok = (int)pos0;
ds4_gpu_routed_moe_cpu(o, model, layer, x0 + (uint64_t)tok * DS4_N_EMBD,
tok, il, DS4_SWIGLU_CLAMP_EXP);
ok = true;
}
if (ok) {
metal_graph_debug_dump_tensor("ffn_moe_gate_clamped", g->batch_routed_gate,
(uint64_t)n_tokens * DS4_N_EXPERT_USED * down_in_dim, il, pos0);
Expand Down Expand Up @@ -27789,3 +27803,15 @@ int ds4_session_ctx(ds4_session *s) {
int ds4_session_prefill_cap(ds4_session *s) {
return s ? (int)s->prefill_cap : 0;
}

/* MoE CPU fallback - calls layer_routed_moe_one_prealloc with simple parameters */
int ds4_gpu_routed_moe_cpu(void *out, const ds4_model *model,
const ds4_layer_weights *layer, const float *x,
int token, uint32_t il, float clamp)
{
block_q8_K xq[16]; /* 16 * 292 = 4672 bytes on stack */
block_q8_K midq[8]; /* 8 * 292 = 2336 bytes */
layer_routed_moe_one_prealloc((float*)out, model, layer, x,
il, token, clamp, NULL, xq, midq);
return 1;
}
2 changes: 2 additions & 0 deletions ds4_agent.c
Original file line number Diff line number Diff line change
Expand Up @@ -592,6 +592,8 @@ static agent_config parse_options(int argc, char **argv) {
c.engine.backend = parse_backend(need_arg(&i, argc, argv, arg));
} else if (!strcmp(arg, "--metal")) {
c.engine.backend = DS4_BACKEND_METAL;
} else if (!strcmp(arg, "--vulkan")) {
c.engine.backend = DS4_BACKEND_CUDA;
} else if (!strcmp(arg, "--cuda")) {
c.engine.backend = DS4_BACKEND_CUDA;
} else if (!strcmp(arg, "--cpu")) {
Expand Down
7 changes: 5 additions & 2 deletions ds4_bench.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ static const char *need_arg(int *i, int argc, char **argv, const char *opt) {

static ds4_backend parse_backend(const char *s, const char *opt) {
if (!strcmp(s, "metal")) return DS4_BACKEND_METAL;
if (!strcmp(s, "vulkan")) return DS4_BACKEND_CUDA;
#ifdef DS4_ROCM_BUILD
if (!strcmp(s, "rocm")) return DS4_BACKEND_CUDA;
#else
Expand All @@ -109,9 +110,9 @@ static ds4_backend parse_backend(const char *s, const char *opt) {
if (!strcmp(s, "cpu")) return DS4_BACKEND_CPU;
fprintf(stderr, "ds4-bench: invalid value for %s: %s\n", opt, s);
#ifdef DS4_ROCM_BUILD
fprintf(stderr, "ds4-bench: valid backends are: metal, rocm, cpu\n");
fprintf(stderr, "ds4-bench: valid backends are: metal, vulkan, rocm, cpu\n");
#else
fprintf(stderr, "ds4-bench: valid backends are: metal, cuda, cpu\n");
fprintf(stderr, "ds4-bench: valid backends are: metal, vulkan, cuda, cpu\n");
#endif
exit(2);
}
Expand Down Expand Up @@ -234,6 +235,8 @@ static bench_config parse_options(int argc, char **argv) {
c.backend = parse_backend(need_arg(&i, argc, argv, arg), arg);
} else if (!strcmp(arg, "--metal")) {
c.backend = DS4_BACKEND_METAL;
} else if (!strcmp(arg, "--vulkan")) {
c.backend = DS4_BACKEND_CUDA;
#ifdef DS4_ROCM_BUILD
} else if (!strcmp(arg, "--rocm")) {
c.backend = DS4_BACKEND_CUDA;
Expand Down
3 changes: 3 additions & 0 deletions ds4_cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ static float parse_float_range(const char *s, const char *opt, float min, float

static ds4_backend parse_backend(const char *s) {
if (!strcmp(s, "metal")) return DS4_BACKEND_METAL;
if (!strcmp(s, "vulkan")) return DS4_BACKEND_CUDA;
#ifdef DS4_ROCM_BUILD
if (!strcmp(s, "rocm")) return DS4_BACKEND_CUDA;
#else
Expand Down Expand Up @@ -1536,6 +1537,8 @@ static cli_config parse_options(int argc, char **argv) {
c.engine.backend = DS4_BACKEND_CPU;
} else if (!strcmp(arg, "--metal")) {
c.engine.backend = DS4_BACKEND_METAL;
} else if (!strcmp(arg, "--vulkan")) {
c.engine.backend = DS4_BACKEND_CUDA;
#ifdef DS4_ROCM_BUILD
} else if (!strcmp(arg, "--rocm")) {
c.engine.backend = DS4_BACKEND_CUDA;
Expand Down
3 changes: 3 additions & 0 deletions ds4_eval.c
Original file line number Diff line number Diff line change
Expand Up @@ -1470,6 +1470,7 @@ static const char *need_arg(int *i, int argc, char **argv, const char *opt) {

static ds4_backend parse_backend(const char *s, const char *opt) {
if (!strcmp(s, "metal")) return DS4_BACKEND_METAL;
if (!strcmp(s, "vulkan")) return DS4_BACKEND_CUDA;
#ifdef DS4_ROCM_BUILD
if (!strcmp(s, "rocm")) return DS4_BACKEND_CUDA;
#else
Expand Down Expand Up @@ -1576,6 +1577,8 @@ static eval_config parse_options(int argc, char **argv) {
c.backend = parse_backend(need_arg(&i, argc, argv, arg), arg);
} else if (!strcmp(arg, "--metal")) {
c.backend = DS4_BACKEND_METAL;
} else if (!strcmp(arg, "--vulkan")) {
c.backend = DS4_BACKEND_CUDA;
#ifdef DS4_ROCM_BUILD
} else if (!strcmp(arg, "--rocm")) {
c.backend = DS4_BACKEND_CUDA;
Expand Down
5 changes: 4 additions & 1 deletion ds4_help.c
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,10 @@ static void print_model_runtime(FILE *fp, const help_colors *c,
ds4_help_tool tool, bool full) {
title(fp, c, "Model And Runtime");
opt(fp, c, "-m, --model FILE", "GGUF model path. Default: ds4flash.gguf");
#ifdef DS4_ROCM_BUILD
#if defined(DS4_VULKAN_BUILD)
opt(fp, c, "--vulkan | --cpu", "Select the backend explicitly.");
opt(fp, c, "--backend NAME", "Backend name: vulkan or cpu.");
#elif defined(DS4_ROCM_BUILD)
opt(fp, c, "--metal | --rocm | --cpu", "Select the backend explicitly.");
opt(fp, c, "--backend NAME", "Backend name: metal, rocm, or cpu.");
#else
Expand Down
9 changes: 7 additions & 2 deletions ds4_rocm.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,13 @@
#include <hipblas/hipblas.h>
#include <hip/hip_fp16.h>
#include <hipcub/hipcub.hpp>
#include <rocwmma/rocwmma-version.hpp>
#include <rocwmma/rocwmma.hpp>
// rocwmma stubs - not actually used in inference code
// #include <rocwmma/rocwmma-version.hpp>
// #include <rocwmma/rocwmma.hpp>
#define ROCWMMA_VERSION_MAJOR 0
#define ROCWMMA_VERSION_MINOR 0
#define ROCWMMA_VERSION_PATCH 0
#define ROCWMMA_VERSION "stub"

#define cudaError_t hipError_t
#define cudaStream_t hipStream_t
Expand Down
7 changes: 5 additions & 2 deletions ds4_server.c
Original file line number Diff line number Diff line change
Expand Up @@ -11485,6 +11485,7 @@ static void usage(FILE *fp, const char *topic) {

static ds4_backend parse_backend_arg(const char *s, const char *arg) {
if (!strcmp(s, "metal")) return DS4_BACKEND_METAL;
if (!strcmp(s, "vulkan")) return DS4_BACKEND_CUDA;
#ifdef DS4_ROCM_BUILD
if (!strcmp(s, "rocm")) return DS4_BACKEND_CUDA;
#else
Expand All @@ -11493,9 +11494,9 @@ static ds4_backend parse_backend_arg(const char *s, const char *arg) {
if (!strcmp(s, "cpu")) return DS4_BACKEND_CPU;
server_log(DS4_LOG_DEFAULT, "ds4-server: invalid %s value: %s", arg, s);
#ifdef DS4_ROCM_BUILD
server_log(DS4_LOG_DEFAULT, "ds4-server: valid server backends are: metal, rocm, cpu");
server_log(DS4_LOG_DEFAULT, "ds4-server: valid server backends are: metal, vulkan, rocm, cpu");
#else
server_log(DS4_LOG_DEFAULT, "ds4-server: valid server backends are: metal, cuda, cpu");
server_log(DS4_LOG_DEFAULT, "ds4-server: valid server backends are: metal, vulkan, cuda, cpu");
#endif
exit(2);
}
Expand Down Expand Up @@ -11654,6 +11655,8 @@ static server_config parse_options(int argc, char **argv) {
c.engine.warm_weights = true;
} else if (!strcmp(arg, "--metal")) {
c.engine.backend = DS4_BACKEND_METAL;
} else if (!strcmp(arg, "--vulkan")) {
c.engine.backend = DS4_BACKEND_CUDA;
#ifdef DS4_ROCM_BUILD
} else if (!strcmp(arg, "--rocm")) {
c.engine.backend = DS4_BACKEND_CUDA;
Expand Down
Loading