Skip to content
Open
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
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