Skip to content
50 changes: 49 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ LIB_M := h3_metal.m h3_gpu.m h3_tokenizer.m
LIB_OBJ := $(LIB_C:.c=.o) $(LIB_M:.m=.o)
CLI_OBJ := main.o h3_cli.o linenoise.o

.PHONY: all test parity real-parity clean
.PHONY: all test parity real-parity clean h3-cuda cuda-spark cuda-generic cuda

all: h3 libh3.a

Expand Down Expand Up @@ -196,6 +196,54 @@ real-parity: h3_real_prompt_test h3_real_dit_block_test
tests/%.o: tests/%.c
$(CC) $(CFLAGS) -I. -c $< -o $@

# ---------------------------------------------------------------------------
# CUDA backend (feat/cuda). The Metal implementation (h3_gpu.m, h3_shaders.metal,
# h3_metal.m, h3_tokenizer.m) is preserved untouched. This builds the CUDA path
# on Linux, replacing the Metal GPU layer with h3_cuda.cu and the Foundation
# tokenizer with h3_tokenizer.c. Usage:
# make cuda-spark DGX Spark / GB10 (omits explicit -arch: fastest on GB10)
# make cuda-generic any local CUDA GPU (nvcc -arch=native)
# make cuda CUDA_ARCH=sm_N explicit arch
CUDA_HOME ?= /usr/local/cuda-13.0
NVCC ?= $(CUDA_HOME)/bin/nvcc
CUDA_ARCH ?= sm_121
CUDA_CFLAGS := -std=c11 -O3 -MMD -MP -Wall -Wextra -Wpedantic -Wshadow \
-Wno-sign-conversion -D_GNU_SOURCE -DH3_CUDA
CUDA_LDLIBS := -L$(CUDA_HOME)/lib64 -lcudart -lcublas -lm

CUDA_C_SRC := h3.c h3_host.c h3_safetensors.c h3_weights.c h3_text_encoder.c \
h3_dit_schedule.c h3_dit.c h3_video_vae.c h3_video_encoder.c h3_audio_vae.c \
h3_ffmpeg.c h3_terminal.c h3_vision_encoder.c h3_multimodal.c h3_tokenizer.c
CUDA_OBJ := $(CUDA_C_SRC:.c=.cuda.o) h3_cuda.cuda.o

CLI_CUDA_OBJ := main.cuda.o h3_cli.cuda.o linenoise.cuda.o

%.cuda.o: %.c
$(CC) $(CUDA_CFLAGS) -I. -c $< -o $@

h3_cuda.cuda.o: h3_cuda.cu h3_gpu.h h3_cuda.h
$(NVCC) -std=c++17 -arch=$(CUDA_ARCH) -I. -DH3_CUDA -c $< -o $@

linenoise.cuda.o: linenoise.c
$(CC) $(CUDA_CFLAGS) -Wno-conversion -Wno-variadic-macro-arguments-omitted -I. -c $< -o $@

h3-cuda: $(CLI_CUDA_OBJ) $(CUDA_OBJ)
$(NVCC) -o h3 $^ $(CUDA_LDLIBS)

cuda-spark:
$(MAKE) -B h3-cuda CUDA_ARCH=sm_121 CC=gcc

cuda-generic:
$(MAKE) -B h3-cuda CUDA_ARCH=native CC=gcc

cuda:
@if [ -z "$(strip $(CUDA_ARCH))" ]; then \
echo "error: specify CUDA_ARCH, e.g. make cuda CUDA_ARCH=sm_120"; \
exit 2; \
fi
$(MAKE) -B h3-cuda CUDA_ARCH="$(CUDA_ARCH)" CC=gcc

# ---------------------------------------------------------------------------
# Vendored from Iris. Keep the main project strict without rewriting this small
# terminal editor for conversion diagnostics unrelated to H3.
linenoise.o: CFLAGS += -Wno-conversion -Wno-variadic-macro-arguments-omitted
Expand Down
18 changes: 18 additions & 0 deletions h3.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
#include "h3_dit.h"
#include "h3_ffmpeg.h"
#include "h3_metal.h"
#ifdef H3_CUDA
#include "h3_cuda.h"
#endif
#include "h3_multimodal.h"
#include "h3_safetensors.h"
#include "h3_text_encoder.h"
Expand Down Expand Up @@ -132,8 +135,13 @@ static int h3_key_file(h3_key *key, const char *role, const char *path) {
strlen(path), path);
return h3_key_append(key, "|%s=%zu:%s:%lld:%lld:%ld", role, strlen(path),
path, (long long)status.st_size,
#ifdef __APPLE__
(long long)status.st_mtimespec.tv_sec,
status.st_mtimespec.tv_nsec);
#else
(long long)status.st_mtim.tv_sec,
status.st_mtim.tv_nsec);
#endif
}

static char *h3_conditioning_key(const char *prompt, const h3_params *params,
Expand Down Expand Up @@ -449,13 +457,23 @@ h3_ctx *h3_load_dir(const char *model_dir) {
h3_free(ctx);
return NULL;
}
#ifdef H3_CUDA
char cuda_error[256];
if (!h3_cuda_probe(&ctx->device, cuda_error, sizeof(cuda_error))) {
h3_set_error(ctx, "%s", cuda_error);
snprintf(h3_global_error, sizeof(h3_global_error), "%s", ctx->error);
h3_free(ctx);
return NULL;
}
#else
char metal_error[256];
if (!h3_metal_probe(&ctx->device, metal_error, sizeof(metal_error))) {
h3_set_error(ctx, "%s", metal_error);
snprintf(h3_global_error, sizeof(h3_global_error), "%s", ctx->error);
h3_free(ctx);
return NULL;
}
#endif
return ctx;
}

Expand Down
8 changes: 8 additions & 0 deletions h3_cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
#include <string.h>
#include <strings.h>
#include <sys/stat.h>
#ifndef __APPLE__
#include <sys/random.h>
#endif
#include <time.h>
#include <unistd.h>

Expand Down Expand Up @@ -103,7 +106,12 @@ static int set_directory(char destination[H3_CLI_PATH], const char *path) {

static uint64_t random_seed(void) {
uint64_t value;
#ifdef __APPLE__
arc4random_buf(&value, sizeof(value));
#else
if (getrandom(&value, sizeof(value), 0) != (ssize_t)sizeof(value))
return (uint64_t)time(NULL);
#endif
return value;
}

Expand Down
Loading