From 69aa9b474c290a5315d894ff1418d3cbd1a1e734 Mon Sep 17 00:00:00 2001 From: magiodev Date: Wed, 12 Aug 2026 20:49:48 +0000 Subject: [PATCH 1/6] feat/cuda: I1 scaffold - CUDA backend skeleton (probe+create/free real, 100 op stubs) - Add h3_cuda.cu: implements the existing plain-C h3_gpu.h API against CUDA/cuBLAS. h3_cuda_probe + h3_gpu_create/free/error real; all compute ops are stubs returning 'not yet implemented'. Metal backend (h3_gpu.m/h3_shaders.metal) preserved untouched. - Add h3_cuda.h (probe decl); h3.c probes via H3_CUDA guard. - Add h3_tokenizer.c C stub (Linux has no Foundation; Metal keeps h3_tokenizer.m). - h3_host.c: vImage high-quality scale guarded, portable bilinear fallback for CUDA build. - h3.c/h3_cli.c/h3_ffmpeg.c: Linux portability guards (st_mtimespec->st_mtim, arc4random_buf->getrandom, SSIZE_MAX define). - Makefile: cuda-spark/cuda-generic/cuda targets (nvcc + cuBLAS, .cuda.o objects, CUDA_ARCH=sm_121 for DGX Spark GB10), mirroring ds4's pattern. --- Makefile | 45 +++- h3.c | 18 ++ h3_cli.c | 8 + h3_cuda.cu | 586 +++++++++++++++++++++++++++++++++++++++++++++++++ h3_cuda.h | 8 + h3_ffmpeg.c | 4 + h3_host.c | 40 +++- h3_tokenizer.c | 59 +++++ 8 files changed, 765 insertions(+), 3 deletions(-) create mode 100644 h3_cuda.cu create mode 100644 h3_cuda.h create mode 100644 h3_tokenizer.c diff --git a/Makefile b/Makefile index bb202379..ecfbac21 100644 --- a/Makefile +++ b/Makefile @@ -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 @@ -196,6 +196,49 @@ 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 + +%.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 $@ + +h3-cuda: $(CLI_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 diff --git a/h3.c b/h3.c index d5dca259..ab4cf7ed 100644 --- a/h3.c +++ b/h3.c @@ -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" @@ -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, @@ -449,6 +457,15 @@ 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); @@ -456,6 +473,7 @@ h3_ctx *h3_load_dir(const char *model_dir) { h3_free(ctx); return NULL; } +#endif return ctx; } diff --git a/h3_cli.c b/h3_cli.c index 79339c82..6ec06745 100644 --- a/h3_cli.c +++ b/h3_cli.c @@ -15,6 +15,9 @@ #include #include #include +#ifndef __APPLE__ +#include +#endif #include #include @@ -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; } diff --git a/h3_cuda.cu b/h3_cuda.cu new file mode 100644 index 00000000..f80662bd --- /dev/null +++ b/h3_cuda.cu @@ -0,0 +1,586 @@ +/* h3_cuda.cu - CUDA backend skeleton for h3.c (feat/cuda). + * Metal backend (h3_gpu.m/h3_shaders.metal) is preserved untouched; + * this file implements the same h3_gpu.h C API against CUDA/cuBLAS. + * I1 scaffold: probe/create/free real, compute ops are stubs. + */ +#include +#include +#include +#include +#include +#include "h3_gpu.h" +#include "h3.h" + +#define H3_CUDA_ERR "CUDA backend: op not yet implemented (feat/cuda)" + +struct h3_gpu { void *dev_ctx; char error[512]; }; +struct h3_gpu_tensor { void *device_ptr; h3_gpu_dtype dtype; size_t elements; }; + +int h3_cuda_probe(h3_device_info *info, char *error, size_t error_size) { + int count = 0; + cudaError_t ce = cudaGetDeviceCount(&count); + if (ce != cudaSuccess || count < 1) { + if (error && error_size) + snprintf(error, error_size, "no CUDA device available: %s", cudaGetErrorString(ce)); + return 0; + } + if (info) { + memset(info, 0, sizeof(*info)); + cudaDeviceProp prop; + cudaGetDeviceProperties(&prop, 0); + snprintf(info->name, sizeof(info->name), "%s", prop.name); + snprintf(info->architecture, sizeof(info->architecture), "sm_%d", prop.major * 100 + prop.minor * 10); + info->physical_memory = (uint64_t)prop.totalGlobalMem; + info->unified_memory = (prop.unifiedMemory ? 1 : 0); + } + return 1; +} +h3_gpu *h3_gpu_create(const char *shader_source_path, char *error, size_t error_size) { + (void)shader_source_path; + h3_gpu *g = (h3_gpu *)calloc(1, sizeof(*g)); + if (!g) { if (error && error_size) snprintf(error, error_size, "oom"); return NULL; } + return g; +} +void h3_gpu_free(h3_gpu *gpu) { if (gpu) free(gpu); } +const char *h3_gpu_error(const h3_gpu *gpu) { + return gpu && gpu->error[0] ? gpu->error : "no error"; +} +static void h3_cuda_seterr(h3_gpu *gpu) { + if (gpu) snprintf(gpu->error, sizeof(gpu->error), "%s", H3_CUDA_ERR); +} + +int h3_gpu_is_m5(const h3_gpu *gpu) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_has_nax_mlp(const h3_gpu *gpu) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_has_int8_mlp(const h3_gpu *gpu) { h3_cuda_seterr(gpu); return 0; } +h3_gpu_tensor * h3_gpu_tensor_new_f32(h3_gpu *gpu, size_t elements) { h3_cuda_seterr(gpu); return NULL; } +h3_gpu_tensor * h3_gpu_tensor_new_bf16(h3_gpu *gpu, size_t elements) { h3_cuda_seterr(gpu); return NULL; } +h3_gpu_tensor * h3_gpu_tensor_new_i8(h3_gpu *gpu, size_t elements) { h3_cuda_seterr(gpu); return NULL; } +h3_gpu_tensor * h3_gpu_tensor_from_f32(h3_gpu *gpu, const float *values, + size_t elements) { h3_cuda_seterr(gpu); return NULL; } +h3_gpu_tensor * h3_gpu_tensor_from_bf16(h3_gpu *gpu, const uint16_t *values, + size_t elements) { h3_cuda_seterr(gpu); return NULL; } +h3_gpu_tensor * h3_gpu_tensor_from_u32(h3_gpu *gpu, const uint32_t *values, + size_t elements) { h3_cuda_seterr(gpu); return NULL; } +h3_gpu_tensor * h3_gpu_tensor_load_bf16(h3_gpu *gpu, const char *path, + uint64_t file_offset, size_t elements) { h3_cuda_seterr(gpu); return NULL; } +h3_gpu_tensor * h3_gpu_tensor_load_f32(h3_gpu *gpu, const char *path, + uint64_t file_offset, size_t elements) { h3_cuda_seterr(gpu); return NULL; } +int h3_gpu_tensor_read_file_bf16(h3_gpu_tensor *tensor, const char *path, + uint64_t file_offset, size_t elements, + char *error, size_t error_size) { return 0; } +int h3_gpu_tensor_stream_file_bf16(h3_gpu_tensor *tensor, const char *path, + uint64_t file_offset, size_t elements, + char *error, size_t error_size) { return 0; } +void h3_gpu_tensor_free(h3_gpu_tensor *tensor) { } +size_t h3_gpu_tensor_elements(const h3_gpu_tensor *tensor) { return 0; } +h3_gpu_dtype h3_gpu_tensor_dtype(const h3_gpu_tensor *tensor) { return 0; } +int h3_gpu_tensor_read_f32(const h3_gpu_tensor *tensor, float *values, + size_t elements) { return 0; } +int h3_gpu_tensor_read_f32_range(const h3_gpu_tensor *tensor, + size_t source_offset, float *values, + size_t elements) { return 0; } +int h3_gpu_tensor_read_bf16(const h3_gpu_tensor *tensor, uint16_t *values, + size_t elements) { return 0; } +int h3_gpu_tensor_write_f32(h3_gpu_tensor *tensor, const float *values, + size_t elements) { return 0; } +int h3_gpu_tensor_write_f32_range(h3_gpu_tensor *tensor, + size_t destination_offset, + const float *values, size_t elements) { return 0; } +int h3_gpu_tensor_write_bf16(h3_gpu_tensor *tensor, const uint16_t *values, + size_t elements) { return 0; } +int h3_gpu_tensor_write_bf16_range(h3_gpu_tensor *tensor, + size_t destination_offset, + const uint16_t *values, size_t elements) { return 0; } +int h3_gpu_begin(h3_gpu *gpu) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_continue(h3_gpu *gpu) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_submit(h3_gpu *gpu) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_get_stats(const h3_gpu *gpu, h3_gpu_stats *stats) { h3_cuda_seterr(gpu); return 0; } +void h3_gpu_profile_set_label(h3_gpu *gpu, const char *label) { h3_cuda_seterr(gpu); } +void h3_gpu_profile_mark(h3_gpu *gpu, const char *phase) { h3_cuda_seterr(gpu); } +int h3_gpu_linear_f32(h3_gpu *gpu, h3_gpu_tensor *output, + const h3_gpu_tensor *input, const h3_gpu_tensor *weight, + const h3_gpu_tensor *bias, uint32_t rows, + uint32_t input_dim, uint32_t output_dim) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_patch_linear_bf16(h3_gpu *gpu, h3_gpu_tensor *output, + const h3_gpu_tensor *input, + const h3_gpu_tensor *weight, + const h3_gpu_tensor *bias, uint32_t rows, + uint32_t input_dim, uint32_t output_dim) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_patch_linear_bf16_offset( + h3_gpu *gpu, h3_gpu_tensor *output, + size_t output_offset, + const h3_gpu_tensor *input, size_t input_offset, + const h3_gpu_tensor *weight, + const h3_gpu_tensor *bias, uint32_t rows, + uint32_t input_dim, uint32_t output_dim) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_patch_linear_bf16_map( + h3_gpu *gpu, h3_gpu_tensor *output, + const h3_gpu_tensor *input, + const h3_gpu_tensor *weight, + const h3_gpu_tensor *bias, + const h3_gpu_tensor *row_map, + uint32_t output_rows, uint32_t rows, + uint32_t input_dim, uint32_t output_dim) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_silu_f32(h3_gpu *gpu, h3_gpu_tensor *output, + const h3_gpu_tensor *input, uint32_t elements) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_cast_f32_to_bf16(h3_gpu *gpu, h3_gpu_tensor *output, + const h3_gpu_tensor *input, uint32_t elements) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_cast_bf16_to_f32(h3_gpu *gpu, h3_gpu_tensor *output, + const h3_gpu_tensor *input, uint32_t elements) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_copy_bf16(h3_gpu *gpu, h3_gpu_tensor *destination, + size_t destination_offset, + const h3_gpu_tensor *source, size_t source_offset, + size_t elements) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_copy_f32(h3_gpu *gpu, h3_gpu_tensor *destination, + size_t destination_offset, + const h3_gpu_tensor *source, size_t source_offset, + size_t elements) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_rms_norm_f32(h3_gpu *gpu, h3_gpu_tensor *output, + const h3_gpu_tensor *input, + const h3_gpu_tensor *weight, uint32_t rows, + uint32_t width, float epsilon) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_adaln_f32(h3_gpu *gpu, h3_gpu_tensor *output, + const h3_gpu_tensor *input, + const h3_gpu_tensor *norm_weight, + const h3_gpu_tensor *modulation, + const h3_gpu_tensor *row_map, uint32_t rows, + uint32_t width, uint32_t slots, uint32_t shift_slot, + uint32_t scale_slot, float epsilon) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_gate_f32(h3_gpu *gpu, h3_gpu_tensor *output, + const h3_gpu_tensor *residual, + const h3_gpu_tensor *branch, + const h3_gpu_tensor *modulation, + const h3_gpu_tensor *row_map, uint32_t rows, + uint32_t width, uint32_t slots, uint32_t gate_slot) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_qkv_rope_f32(h3_gpu *gpu, h3_gpu_tensor *query, + h3_gpu_tensor *key, h3_gpu_tensor *value, + const h3_gpu_tensor *qkv, + const h3_gpu_tensor *q_norm, + const h3_gpu_tensor *k_norm, + const h3_gpu_tensor *rope_cos, + const h3_gpu_tensor *rope_sin, uint32_t sequence, + uint32_t heads, uint32_t head_dim, + uint32_t rope_half, float epsilon) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_sdpa_f32(h3_gpu *gpu, h3_gpu_tensor *output, + const h3_gpu_tensor *query, const h3_gpu_tensor *key, + const h3_gpu_tensor *value, uint32_t sequence, + uint32_t heads, uint32_t head_dim, float scale) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_swiglu_f32(h3_gpu *gpu, h3_gpu_tensor *output, + const h3_gpu_tensor *fused, uint32_t rows, + uint32_t width) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_scale_add_f32(h3_gpu *gpu, h3_gpu_tensor *output, + const h3_gpu_tensor *residual, + const h3_gpu_tensor *branch, + const h3_gpu_tensor *scale, uint32_t rows, + uint32_t width) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_layer_norm_f32(h3_gpu *gpu, h3_gpu_tensor *output, + const h3_gpu_tensor *input, + const h3_gpu_tensor *weight, + const h3_gpu_tensor *bias, uint32_t rows, + uint32_t width, float epsilon) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_video_qkv_rope_f32(h3_gpu *gpu, h3_gpu_tensor *query, + h3_gpu_tensor *key, h3_gpu_tensor *value, + const h3_gpu_tensor *qkv, + const h3_gpu_tensor *rope_cos, + const h3_gpu_tensor *rope_sin, + uint32_t sequence, uint32_t heads, + uint32_t head_dim, uint32_t rope_half, + float epsilon) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_conv1d_f32(h3_gpu *gpu, h3_gpu_tensor *output, + const h3_gpu_tensor *input, + const h3_gpu_tensor *weight, + const h3_gpu_tensor *bias, uint32_t batch, + uint32_t length, uint32_t input_channels, + uint32_t output_channels, uint32_t kernel, + uint32_t padding, uint32_t dilation) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_conv1d_stride_f32(h3_gpu *gpu, h3_gpu_tensor *output, + const h3_gpu_tensor *input, + const h3_gpu_tensor *weight, + const h3_gpu_tensor *bias, uint32_t batch, + uint32_t length, uint32_t input_channels, + uint32_t output_channels, uint32_t kernel, + uint32_t stride, uint32_t padding, + uint32_t dilation) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_conv_transpose1d_f32( + h3_gpu *gpu, h3_gpu_tensor *output, + const h3_gpu_tensor *input, + const h3_gpu_tensor *weight, + const h3_gpu_tensor *bias, uint32_t batch, + uint32_t length, uint32_t input_channels, + uint32_t output_channels, uint32_t kernel, + uint32_t stride, uint32_t padding) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_weight_norm_f32(h3_gpu *gpu, h3_gpu_tensor *output, + const h3_gpu_tensor *vector, + const h3_gpu_tensor *magnitude, + uint32_t outer, uint32_t inner) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_add_scaled_f32(h3_gpu *gpu, h3_gpu_tensor *output, + const h3_gpu_tensor *left, + const h3_gpu_tensor *right, float left_scale, + float right_scale, uint32_t elements) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_alias_free_snake_f32( + h3_gpu *gpu, h3_gpu_tensor *output, + const h3_gpu_tensor *input, + const h3_gpu_tensor *alpha_log, + const h3_gpu_tensor *beta_log, + const h3_gpu_tensor *upsample_filter, + const h3_gpu_tensor *downsample_filter, + uint32_t batch, uint32_t length, + uint32_t channels) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_snake1d_f32(h3_gpu *gpu, h3_gpu_tensor *output, + const h3_gpu_tensor *input, + const h3_gpu_tensor *alpha, uint32_t batch, + uint32_t length, uint32_t channels) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_audio_qkv_split_f32(h3_gpu *gpu, + h3_gpu_tensor *query, h3_gpu_tensor *key, + h3_gpu_tensor *value, const h3_gpu_tensor *qkv, + const h3_gpu_tensor *q_bias, + const h3_gpu_tensor *k_bias, + const h3_gpu_tensor *v_bias, uint32_t batch, + uint32_t length, uint32_t heads, + uint32_t head_dim) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_sdpa_causal_f32(h3_gpu *gpu, h3_gpu_tensor *output, + const h3_gpu_tensor *query, + const h3_gpu_tensor *key, + const h3_gpu_tensor *value, uint32_t batch, + uint32_t sequence, uint32_t heads, + uint32_t head_dim, float scale) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_audio_attention_pool_f32(h3_gpu *gpu, + h3_gpu_tensor *output, + const h3_gpu_tensor *attended, uint32_t batch, + uint32_t length, uint32_t heads, + uint32_t head_dim, uint32_t output_dim) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_geglu_f32(h3_gpu *gpu, h3_gpu_tensor *output, + const h3_gpu_tensor *gate, + const h3_gpu_tensor *linear, uint32_t elements) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_clip_f32(h3_gpu *gpu, h3_gpu_tensor *output, + const h3_gpu_tensor *input, uint32_t elements, + float minimum, float maximum) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_vae_encoder_pad_f32( + h3_gpu *gpu, h3_gpu_tensor *output, + const h3_gpu_tensor *input, uint32_t batch, + uint32_t depth, uint32_t height, uint32_t width, + uint32_t channels, uint32_t depth_front, + uint32_t height_before, uint32_t height_after, + uint32_t width_before, uint32_t width_after) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_conv3d_f32(h3_gpu *gpu, h3_gpu_tensor *output, + const h3_gpu_tensor *input, + const h3_gpu_tensor *weight, + const h3_gpu_tensor *bias, uint32_t batch, + uint32_t depth, uint32_t height, uint32_t width, + uint32_t input_channels, uint32_t output_channels, + uint32_t kernel_depth, uint32_t kernel_height, + uint32_t kernel_width, uint32_t stride_depth, + uint32_t stride_height, uint32_t stride_width) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_vae_encoder_group_norm_silu_f32( + h3_gpu *gpu, h3_gpu_tensor *output, + const h3_gpu_tensor *input, + const h3_gpu_tensor *weight, + const h3_gpu_tensor *bias, uint32_t batch, + uint32_t depth, uint32_t height, uint32_t width, + uint32_t channels, uint32_t groups, float epsilon) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_linear_bf16(h3_gpu *gpu, h3_gpu_tensor *output, + const h3_gpu_tensor *input, + const h3_gpu_tensor *weight, + const h3_gpu_tensor *bias, uint32_t rows, + uint32_t input_dim, uint32_t output_dim) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_mlp_bf16(h3_gpu *gpu, h3_gpu_tensor *output, + const h3_gpu_tensor *input, + const h3_gpu_tensor *fc1_weight, + const h3_gpu_tensor *fc2_weight, uint32_t rows, + uint32_t input_dim, uint32_t hidden_dim, + uint32_t output_dim) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_mlp_nax_bf16(h3_gpu *gpu, h3_gpu_tensor *output, + h3_gpu_tensor *activated, + const h3_gpu_tensor *input, + const h3_gpu_tensor *fc1_weight, + const h3_gpu_tensor *fc2_weight, uint32_t rows, + uint32_t input_dim, uint32_t hidden_dim, + uint32_t output_dim) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_quantize_weight_int8(h3_gpu *gpu, h3_gpu_tensor *output, + h3_gpu_tensor *scales, + const h3_gpu_tensor *input, uint32_t rows, + uint32_t columns) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_linear_int8_bf16(h3_gpu *gpu, h3_gpu_tensor *output, + h3_gpu_tensor *quantized_input, + h3_gpu_tensor *input_scales, + const h3_gpu_tensor *input, + const h3_gpu_tensor *weight, + const h3_gpu_tensor *weight_scales, + uint32_t rows, uint32_t input_dim, + uint32_t output_dim, + int use_slower_uncached_int8_scales) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_linear_int8_head_major_bf16( + h3_gpu *gpu, h3_gpu_tensor *output, + h3_gpu_tensor *quantized_input, + h3_gpu_tensor *input_scales, + const h3_gpu_tensor *input, + const h3_gpu_tensor *weight, + const h3_gpu_tensor *weight_scales, + uint32_t rows, uint32_t heads, + uint32_t head_dim, uint32_t output_dim) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_mlp_int8_bf16(h3_gpu *gpu, h3_gpu_tensor *output, + h3_gpu_tensor *activated, + h3_gpu_tensor *quantized_activation, + h3_gpu_tensor *activation_scales, + const h3_gpu_tensor *input, + const h3_gpu_tensor *fc1_weight, + const h3_gpu_tensor *fc1_scales, + const h3_gpu_tensor *fc2_weight, + const h3_gpu_tensor *fc2_scales, + const h3_gpu_tensor *fc1_bf16, + const h3_gpu_tensor *fc2_bf16, uint32_t rows, + uint32_t input_dim, uint32_t hidden_dim, + uint32_t output_dim, + int use_slower_grouped_quantizer, + int use_slower_dynamic_fc1_k, + int use_int8_row_fc2, + int input_is_quantized) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_silu_bf16(h3_gpu *gpu, h3_gpu_tensor *output, + const h3_gpu_tensor *input, uint32_t elements) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_rms_norm_bf16(h3_gpu *gpu, h3_gpu_tensor *output, + const h3_gpu_tensor *input, + const h3_gpu_tensor *weight, uint32_t rows, + uint32_t width, float epsilon) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_layer_norm_bf16(h3_gpu *gpu, h3_gpu_tensor *output, + const h3_gpu_tensor *input, + const h3_gpu_tensor *weight, + const h3_gpu_tensor *bias, uint32_t rows, + uint32_t width, float epsilon) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_gelu_bf16(h3_gpu *gpu, h3_gpu_tensor *output, + const h3_gpu_tensor *input, uint32_t elements, + int approximate) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_vision_qkv_rope_bf16( + h3_gpu *gpu, h3_gpu_tensor *query, + h3_gpu_tensor *key, h3_gpu_tensor *value, + const h3_gpu_tensor *qkv, + const h3_gpu_tensor *rope_cos, + const h3_gpu_tensor *rope_sin, uint32_t sequence, + uint32_t heads, uint32_t head_dim, + uint32_t rope_half) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_adaln_bf16(h3_gpu *gpu, h3_gpu_tensor *output, + const h3_gpu_tensor *input, + const h3_gpu_tensor *norm_weight, + const h3_gpu_tensor *modulation, + const h3_gpu_tensor *row_map, uint32_t rows, + uint32_t width, uint32_t slots, uint32_t shift_slot, + uint32_t scale_slot, float epsilon) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_adaln_bf16_offset(h3_gpu *gpu, h3_gpu_tensor *output, + const h3_gpu_tensor *input, size_t input_offset, + const h3_gpu_tensor *norm_weight, + const h3_gpu_tensor *modulation, + const h3_gpu_tensor *row_map, uint32_t rows, + uint32_t width, uint32_t slots, uint32_t shift_slot, + uint32_t scale_slot, float epsilon) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_adaln_linear_bf16( + h3_gpu *gpu, h3_gpu_tensor *output, + h3_gpu_tensor *inverse, + const h3_gpu_tensor *input, size_t input_offset, + const h3_gpu_tensor *norm_weight, + const h3_gpu_tensor *modulation, + const h3_gpu_tensor *row_map, + const h3_gpu_tensor *weight, + const h3_gpu_tensor *bias, uint32_t rows, + uint32_t width, uint32_t output_dim, uint32_t slots, + uint32_t shift_slot, uint32_t scale_slot, + float epsilon) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_gate_bf16(h3_gpu *gpu, h3_gpu_tensor *output, + const h3_gpu_tensor *residual, + const h3_gpu_tensor *branch, + const h3_gpu_tensor *modulation, + const h3_gpu_tensor *row_map, uint32_t rows, + uint32_t width, uint32_t slots, uint32_t gate_slot) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_gate_adaln_bf16( + h3_gpu *gpu, h3_gpu_tensor *gated_residual, + h3_gpu_tensor *output, + const h3_gpu_tensor *residual, + const h3_gpu_tensor *branch, + const h3_gpu_tensor *norm_weight, + const h3_gpu_tensor *gate_modulation, + const h3_gpu_tensor *norm_modulation, + const h3_gpu_tensor *row_map, uint32_t rows, + uint32_t width, uint32_t slots, uint32_t gate_slot, + uint32_t shift_slot, uint32_t scale_slot, + float epsilon) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_gate_adaln_quantize_int8( + h3_gpu *gpu, h3_gpu_tensor *gated_residual, + h3_gpu_tensor *quantized_output, + h3_gpu_tensor *quantized_scales, + const h3_gpu_tensor *residual, + const h3_gpu_tensor *branch, + const h3_gpu_tensor *norm_weight, + const h3_gpu_tensor *gate_modulation, + const h3_gpu_tensor *norm_modulation, + const h3_gpu_tensor *row_map, uint32_t rows, + uint32_t padded_rows, uint32_t width, uint32_t slots, + uint32_t gate_slot, uint32_t shift_slot, + uint32_t scale_slot, float epsilon) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_qkv_rope_bf16(h3_gpu *gpu, h3_gpu_tensor *query, + h3_gpu_tensor *key, h3_gpu_tensor *value, + const h3_gpu_tensor *qkv, + const h3_gpu_tensor *q_norm, + const h3_gpu_tensor *k_norm, + const h3_gpu_tensor *rope_cos, + const h3_gpu_tensor *rope_sin, uint32_t sequence, + uint32_t heads, uint32_t head_dim, + uint32_t rope_half, float epsilon) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_grouped_qkv_rope_bf16(h3_gpu *gpu, h3_gpu_tensor *query, + h3_gpu_tensor *key, h3_gpu_tensor *value, + const h3_gpu_tensor *qkv, + const h3_gpu_tensor *q_norm, + const h3_gpu_tensor *k_norm, + const h3_gpu_tensor *rope_cos, + const h3_gpu_tensor *rope_sin, + uint32_t sequence, uint32_t heads, + uint32_t head_dim, uint32_t rope_half, + float epsilon) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_grouped_qkv_linear_rope_bf16( + h3_gpu *gpu, + h3_gpu_tensor *query, + h3_gpu_tensor *key, + h3_gpu_tensor *value, + h3_gpu_tensor *qkv, + const h3_gpu_tensor *input, + const h3_gpu_tensor *weight, + const h3_gpu_tensor *q_norm, + const h3_gpu_tensor *k_norm, + const h3_gpu_tensor *rope_cos, + const h3_gpu_tensor *rope_sin, + uint32_t rows, uint32_t input_dim, + uint32_t heads, uint32_t head_dim, + uint32_t rope_half, float epsilon) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_grouped_qkv_linear_rope_int8( + h3_gpu *gpu, + h3_gpu_tensor *query, + h3_gpu_tensor *key, + h3_gpu_tensor *value, + h3_gpu_tensor *quantized_input, + h3_gpu_tensor *input_scales, + const h3_gpu_tensor *input, + const h3_gpu_tensor *weight, + const h3_gpu_tensor *weight_scales, + const h3_gpu_tensor *q_norm, + const h3_gpu_tensor *k_norm, + const h3_gpu_tensor *rope_cos, + const h3_gpu_tensor *rope_sin, + uint32_t rows, uint32_t input_dim, + uint32_t heads, uint32_t head_dim, + uint32_t rope_half, float epsilon, + int input_is_quantized, + int use_slower_unfused_qkv_rope, + int use_slower_scalar_qkv_rms, + int use_slower_uncached_int8_scales) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_sdpa_bf16(h3_gpu *gpu, h3_gpu_tensor *output, + const h3_gpu_tensor *query, const h3_gpu_tensor *key, + const h3_gpu_tensor *value, uint32_t sequence, + uint32_t heads, uint32_t head_dim, float scale) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_sdpa_bf16_head_major_output( + h3_gpu *gpu, h3_gpu_tensor *output, + const h3_gpu_tensor *query, const h3_gpu_tensor *key, + const h3_gpu_tensor *value, uint32_t sequence, + uint32_t heads, uint32_t head_dim, float scale) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_swiglu_bf16(h3_gpu *gpu, h3_gpu_tensor *output, + const h3_gpu_tensor *fused, uint32_t rows, + uint32_t width) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_embedding_bf16(h3_gpu *gpu, h3_gpu_tensor *output, + const h3_gpu_tensor *weight, + const h3_gpu_tensor *token_ids, uint32_t tokens, + uint32_t vocab_size, uint32_t width) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_text_qk_rope_bf16(h3_gpu *gpu, + h3_gpu_tensor *query_output, + h3_gpu_tensor *key_output, + const h3_gpu_tensor *query_input, + const h3_gpu_tensor *key_input, + const h3_gpu_tensor *q_norm, + const h3_gpu_tensor *k_norm, + const h3_gpu_tensor *rope_cos, + const h3_gpu_tensor *rope_sin, + uint32_t sequence, uint32_t query_heads, + uint32_t kv_heads, uint32_t head_dim, + float epsilon) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_head_rms_norm_bf16(h3_gpu *gpu, h3_gpu_tensor *tensor, + const h3_gpu_tensor *weight, + uint32_t sequence, uint32_t heads, + uint32_t head_dim, float epsilon) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_rope_text_bf16(h3_gpu *gpu, h3_gpu_tensor *query, + h3_gpu_tensor *key, + const h3_gpu_tensor *rope_cos_f32, + const h3_gpu_tensor *rope_sin_f32, + uint32_t sequence, uint32_t query_heads, + uint32_t kv_heads, uint32_t head_dim) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_gqa_causal_bf16(h3_gpu *gpu, h3_gpu_tensor *output, + const h3_gpu_tensor *query, + const h3_gpu_tensor *key, + const h3_gpu_tensor *value, + uint32_t sequence, uint32_t query_heads, + uint32_t kv_heads, uint32_t head_dim, + float scale) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_add_bf16(h3_gpu *gpu, h3_gpu_tensor *output, + const h3_gpu_tensor *left, const h3_gpu_tensor *right, + uint32_t elements) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_sub_bf16(h3_gpu *gpu, h3_gpu_tensor *output, + const h3_gpu_tensor *left, const h3_gpu_tensor *right, + uint32_t elements) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_token_pool_bf16(h3_gpu *gpu, h3_gpu_tensor *output, + const h3_gpu_tensor *input, + size_t input_offset, + h3_gpu_tensor *original, + size_t original_offset, + h3_gpu_tensor *baseline, + size_t baseline_offset, + const h3_gpu_tensor *baseline_indices, + const h3_gpu_tensor *pairs, uint32_t input_rows, + uint32_t rows, uint32_t baseline_rows, + uint32_t width) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_token_pool_adaln_bf16( + h3_gpu *gpu, h3_gpu_tensor *residual, + h3_gpu_tensor *output, + const h3_gpu_tensor *input, size_t input_offset, + h3_gpu_tensor *original, size_t original_offset, + h3_gpu_tensor *baseline, size_t baseline_offset, + const h3_gpu_tensor *baseline_indices, + const h3_gpu_tensor *pairs, + const h3_gpu_tensor *norm_weight, + const h3_gpu_tensor *modulation, + const h3_gpu_tensor *row_map, + uint32_t input_rows, uint32_t rows, + uint32_t baseline_rows, uint32_t width, + uint32_t slots, uint32_t shift_slot, + uint32_t scale_slot, float epsilon) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_token_expand_delta_bf16( + h3_gpu *gpu, h3_gpu_tensor *output, + const h3_gpu_tensor *original, + size_t original_offset, + const h3_gpu_tensor *reduced, + const h3_gpu_tensor *baseline, + size_t baseline_offset, + const h3_gpu_tensor *baseline_indices, + const h3_gpu_tensor *parents, uint32_t rows, + uint32_t reduced_rows, uint32_t baseline_rows, + uint32_t width, + uint32_t exact_prefix_rows, + float update_scale) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_token_expand_adaln_bf16( + h3_gpu *gpu, h3_gpu_tensor *residual, + h3_gpu_tensor *output, + const h3_gpu_tensor *original, + size_t original_offset, + const h3_gpu_tensor *reduced, + const h3_gpu_tensor *baseline, + size_t baseline_offset, + const h3_gpu_tensor *baseline_indices, + const h3_gpu_tensor *parents, + const h3_gpu_tensor *norm_weight, + const h3_gpu_tensor *modulation, + const h3_gpu_tensor *row_map, + uint32_t rows, uint32_t reduced_rows, + uint32_t baseline_rows, uint32_t width, + uint32_t exact_prefix_rows, float update_scale, + uint32_t slots, uint32_t shift_slot, + uint32_t scale_slot, float epsilon) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_euler_bf16(h3_gpu *gpu, h3_gpu_tensor *sample, + size_t sample_offset, const h3_gpu_tensor *last, + const h3_gpu_tensor *previous, uint32_t elements, + float delta, float ratio) { h3_cuda_seterr(gpu); return 0; } +int h3_gpu_silu_mul_bf16(h3_gpu *gpu, h3_gpu_tensor *output, + const h3_gpu_tensor *gate, + const h3_gpu_tensor *up, uint32_t elements) { h3_cuda_seterr(gpu); return 0; } diff --git a/h3_cuda.h b/h3_cuda.h new file mode 100644 index 00000000..f5eb09ee --- /dev/null +++ b/h3_cuda.h @@ -0,0 +1,8 @@ +#ifndef H3_CUDA_H +#define H3_CUDA_H + +#include "h3.h" + +int h3_cuda_probe(h3_device_info *info, char *error, size_t error_size); + +#endif diff --git a/h3_ffmpeg.c b/h3_ffmpeg.c index 66762425..cb730f3e 100644 --- a/h3_ffmpeg.c +++ b/h3_ffmpeg.c @@ -12,6 +12,10 @@ #include #include +#ifndef SSIZE_MAX +#define SSIZE_MAX ((ssize_t)(~((size_t)0) >> 1)) +#endif + extern char **environ; static const char *ffmpeg_program(void) { diff --git a/h3_host.c b/h3_host.c index a04a2a0a..d637d92a 100644 --- a/h3_host.c +++ b/h3_host.c @@ -1,6 +1,8 @@ #include "h3_host.h" +#ifndef H3_CUDA #include +#endif #include #include @@ -555,14 +557,15 @@ int h3_resize_rgb24_high_quality(const uint8_t *input, int frames, free(pixels); return 0; } + size_t input_frame_bytes = input_area * 3; + size_t output_frame_bytes = output_area * 3; +#ifndef H3_CUDA uint8_t *source_argb = malloc(input_area * 4); uint8_t *output_argb = malloc(output_area * 4); if (!source_argb || !output_argb) { free(source_argb); free(output_argb); free(pixels); return 0; } - size_t input_frame_bytes = input_area * 3; - size_t output_frame_bytes = output_area * 3; vImage_Buffer source_buffer = { source_argb, (vImagePixelCount)input_height, (vImagePixelCount)input_width, (size_t)input_width * 4 @@ -594,6 +597,39 @@ int h3_resize_rgb24_high_quality(const uint8_t *input, int frames, } } free(source_argb); free(output_argb); +#else + /* Portable bilinear RGB24 resize (CUDA build; Metal keeps vImage). */ + for (int frame = 0; frame < frames; frame++) { + const uint8_t *src = input + (size_t)frame * input_frame_bytes; + uint8_t *dst = pixels + (size_t)frame * output_frame_bytes; + for (size_t y = 0; y < output_height; y++) { + float gy = (output_height == 1) ? 0.0f : + (float)y * (input_height - 1) / (output_height - 1); + int y0 = (int)gy; + if (y0 > input_height - 2) y0 = input_height - 2; + float fy = gy - (float)y0; + for (size_t x = 0; x < output_width; x++) { + float gx = (output_width == 1) ? 0.0f : + (float)x * (input_width - 1) / (output_width - 1); + int x0 = (int)gx; + if (x0 > input_width - 2) x0 = input_width - 2; + float fx = gx - (float)x0; + const uint8_t *p00 = src + ((size_t)y0 * input_width + x0) * 3; + const uint8_t *p10 = p00 + 3; + const uint8_t *p01 = src + ((size_t)(y0 + 1) * input_width + x0) * 3; + const uint8_t *p11 = p01 + 3; + uint8_t *o = dst + (y * output_width + x) * 3; + for (int c = 0; c < 3; c++) { + float v = (1.0f - fy) * (1.0f - fx) * p00[c] + + (1.0f - fy) * fx * p10[c] + + fy * (1.0f - fx) * p01[c] + + fy * fx * p11[c]; + o[c] = (uint8_t)(v + 0.5f); + } + } + } + } +#endif *output = pixels; return 1; } diff --git a/h3_tokenizer.c b/h3_tokenizer.c new file mode 100644 index 00000000..3993390e --- /dev/null +++ b/h3_tokenizer.c @@ -0,0 +1,59 @@ +/* h3_tokenizer.c - C stub for the CUDA/Linux build (feat/cuda). + * + * The Metal build uses h3_tokenizer.m (Objective-C/Foundation). On Linux there + * is no Foundation, so the CUDA build compiles this C file against the same + * h3_tokenizer.h API. It is a scaffold stub for I1: it satisfies the link so + * the host binary builds and `--info` runs. Real tokenizer port is a later + * iteration (I20). Generation paths that need tokenization return an error. + */ +#include "h3_tokenizer.h" + +#include +#include +#include + +struct h3_tokenizer { + int unused; +}; + +h3_tokenizer *h3_tokenizer_load(const char *tokenizer_json, + char *error, size_t error_size) { + (void)tokenizer_json; + if (error && error_size) { + snprintf(error, error_size, + "CUDA build: tokenizer not yet ported (feat/cuda)"); + } + return NULL; +} + +void h3_tokenizer_free(h3_tokenizer *tokenizer) { + (void)tokenizer; +} + +int h3_tokenizer_encode(const h3_tokenizer *tokenizer, const char *utf8, + int pad_empty, uint32_t **ids, size_t *count, + char *error, size_t error_size) { + (void)tokenizer; (void)utf8; (void)pad_empty; + if (ids) *ids = NULL; + if (count) *count = 0; + if (error && error_size) { + snprintf(error, error_size, + "CUDA build: tokenizer not yet ported (feat/cuda)"); + } + return 0; +} + +void h3_tokenizer_ids_free(uint32_t *ids) { + free(ids); +} + +char *h3_tokenizer_decode(const h3_tokenizer *tokenizer, + const uint32_t *ids, size_t count, + char *error, size_t error_size) { + (void)tokenizer; (void)ids; (void)count; + if (error && error_size) { + snprintf(error, error_size, + "CUDA build: tokenizer not yet ported (feat/cuda)"); + } + return NULL; +} From c0d92e155baa87e1337df68c2e47a208d6b3b318 Mon Sep 17 00:00:00 2001 From: magiodev Date: Wed, 12 Aug 2026 20:53:23 +0000 Subject: [PATCH 2/6] feat/cuda: build CLI objects as .cuda.o with -D_GNU_SOURCE (Linux CLOCK_MONOTONIC/strdup) --- Makefile | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index ecfbac21..49560b74 100644 --- a/Makefile +++ b/Makefile @@ -216,13 +216,18 @@ CUDA_C_SRC := h3.c h3_host.c h3_safetensors.c h3_weights.c h3_text_encoder.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 $@ -h3-cuda: $(CLI_OBJ) $(CUDA_OBJ) +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: From cd0e18bf94a77e0ba855da43ab9dcdcf8d55f996 Mon Sep 17 00:00:00 2001 From: magiodev Date: Wed, 12 Aug 2026 20:58:06 +0000 Subject: [PATCH 3/6] feat/cuda: fix nvcc strictness - seterr takes const h3_gpu*, stub returns cast to exact type --- h3_cuda.cu | 198 ++++++++++++++++++++++++++--------------------------- 1 file changed, 99 insertions(+), 99 deletions(-) diff --git a/h3_cuda.cu b/h3_cuda.cu index f80662bd..9440463e 100644 --- a/h3_cuda.cu +++ b/h3_cuda.cu @@ -45,74 +45,74 @@ void h3_gpu_free(h3_gpu *gpu) { if (gpu) free(gpu); } const char *h3_gpu_error(const h3_gpu *gpu) { return gpu && gpu->error[0] ? gpu->error : "no error"; } -static void h3_cuda_seterr(h3_gpu *gpu) { - if (gpu) snprintf(gpu->error, sizeof(gpu->error), "%s", H3_CUDA_ERR); +static void h3_cuda_seterr(const h3_gpu *gpu) { + if (gpu) snprintf(((h3_gpu *)gpu)->error, sizeof(((h3_gpu *)gpu)->error), "%s", H3_CUDA_ERR); } -int h3_gpu_is_m5(const h3_gpu *gpu) { h3_cuda_seterr(gpu); return 0; } -int h3_gpu_has_nax_mlp(const h3_gpu *gpu) { h3_cuda_seterr(gpu); return 0; } -int h3_gpu_has_int8_mlp(const h3_gpu *gpu) { h3_cuda_seterr(gpu); return 0; } -h3_gpu_tensor * h3_gpu_tensor_new_f32(h3_gpu *gpu, size_t elements) { h3_cuda_seterr(gpu); return NULL; } -h3_gpu_tensor * h3_gpu_tensor_new_bf16(h3_gpu *gpu, size_t elements) { h3_cuda_seterr(gpu); return NULL; } -h3_gpu_tensor * h3_gpu_tensor_new_i8(h3_gpu *gpu, size_t elements) { h3_cuda_seterr(gpu); return NULL; } +int h3_gpu_is_m5(const h3_gpu *gpu) { h3_cuda_seterr(gpu); return (int)0; } +int h3_gpu_has_nax_mlp(const h3_gpu *gpu) { h3_cuda_seterr(gpu); return (int)0; } +int h3_gpu_has_int8_mlp(const h3_gpu *gpu) { h3_cuda_seterr(gpu); return (int)0; } +h3_gpu_tensor * h3_gpu_tensor_new_f32(h3_gpu *gpu, size_t elements) { h3_cuda_seterr(gpu); return (h3_gpu_tensor *)NULL; } +h3_gpu_tensor * h3_gpu_tensor_new_bf16(h3_gpu *gpu, size_t elements) { h3_cuda_seterr(gpu); return (h3_gpu_tensor *)NULL; } +h3_gpu_tensor * h3_gpu_tensor_new_i8(h3_gpu *gpu, size_t elements) { h3_cuda_seterr(gpu); return (h3_gpu_tensor *)NULL; } h3_gpu_tensor * h3_gpu_tensor_from_f32(h3_gpu *gpu, const float *values, - size_t elements) { h3_cuda_seterr(gpu); return NULL; } + size_t elements) { h3_cuda_seterr(gpu); return (h3_gpu_tensor *)NULL; } h3_gpu_tensor * h3_gpu_tensor_from_bf16(h3_gpu *gpu, const uint16_t *values, - size_t elements) { h3_cuda_seterr(gpu); return NULL; } + size_t elements) { h3_cuda_seterr(gpu); return (h3_gpu_tensor *)NULL; } h3_gpu_tensor * h3_gpu_tensor_from_u32(h3_gpu *gpu, const uint32_t *values, - size_t elements) { h3_cuda_seterr(gpu); return NULL; } + size_t elements) { h3_cuda_seterr(gpu); return (h3_gpu_tensor *)NULL; } h3_gpu_tensor * h3_gpu_tensor_load_bf16(h3_gpu *gpu, const char *path, - uint64_t file_offset, size_t elements) { h3_cuda_seterr(gpu); return NULL; } + uint64_t file_offset, size_t elements) { h3_cuda_seterr(gpu); return (h3_gpu_tensor *)NULL; } h3_gpu_tensor * h3_gpu_tensor_load_f32(h3_gpu *gpu, const char *path, - uint64_t file_offset, size_t elements) { h3_cuda_seterr(gpu); return NULL; } + uint64_t file_offset, size_t elements) { h3_cuda_seterr(gpu); return (h3_gpu_tensor *)NULL; } int h3_gpu_tensor_read_file_bf16(h3_gpu_tensor *tensor, const char *path, uint64_t file_offset, size_t elements, - char *error, size_t error_size) { return 0; } + char *error, size_t error_size) { return (int)0; } int h3_gpu_tensor_stream_file_bf16(h3_gpu_tensor *tensor, const char *path, uint64_t file_offset, size_t elements, - char *error, size_t error_size) { return 0; } + char *error, size_t error_size) { return (int)0; } void h3_gpu_tensor_free(h3_gpu_tensor *tensor) { } -size_t h3_gpu_tensor_elements(const h3_gpu_tensor *tensor) { return 0; } -h3_gpu_dtype h3_gpu_tensor_dtype(const h3_gpu_tensor *tensor) { return 0; } +size_t h3_gpu_tensor_elements(const h3_gpu_tensor *tensor) { return (size_t)0; } +h3_gpu_dtype h3_gpu_tensor_dtype(const h3_gpu_tensor *tensor) { return (h3_gpu_dtype)0; } int h3_gpu_tensor_read_f32(const h3_gpu_tensor *tensor, float *values, - size_t elements) { return 0; } + size_t elements) { return (int)0; } int h3_gpu_tensor_read_f32_range(const h3_gpu_tensor *tensor, size_t source_offset, float *values, - size_t elements) { return 0; } + size_t elements) { return (int)0; } int h3_gpu_tensor_read_bf16(const h3_gpu_tensor *tensor, uint16_t *values, - size_t elements) { return 0; } + size_t elements) { return (int)0; } int h3_gpu_tensor_write_f32(h3_gpu_tensor *tensor, const float *values, - size_t elements) { return 0; } + size_t elements) { return (int)0; } int h3_gpu_tensor_write_f32_range(h3_gpu_tensor *tensor, size_t destination_offset, - const float *values, size_t elements) { return 0; } + const float *values, size_t elements) { return (int)0; } int h3_gpu_tensor_write_bf16(h3_gpu_tensor *tensor, const uint16_t *values, - size_t elements) { return 0; } + size_t elements) { return (int)0; } int h3_gpu_tensor_write_bf16_range(h3_gpu_tensor *tensor, size_t destination_offset, - const uint16_t *values, size_t elements) { return 0; } -int h3_gpu_begin(h3_gpu *gpu) { h3_cuda_seterr(gpu); return 0; } -int h3_gpu_continue(h3_gpu *gpu) { h3_cuda_seterr(gpu); return 0; } -int h3_gpu_submit(h3_gpu *gpu) { h3_cuda_seterr(gpu); return 0; } -int h3_gpu_get_stats(const h3_gpu *gpu, h3_gpu_stats *stats) { h3_cuda_seterr(gpu); return 0; } + const uint16_t *values, size_t elements) { return (int)0; } +int h3_gpu_begin(h3_gpu *gpu) { h3_cuda_seterr(gpu); return (int)0; } +int h3_gpu_continue(h3_gpu *gpu) { h3_cuda_seterr(gpu); return (int)0; } +int h3_gpu_submit(h3_gpu *gpu) { h3_cuda_seterr(gpu); return (int)0; } +int h3_gpu_get_stats(const h3_gpu *gpu, h3_gpu_stats *stats) { h3_cuda_seterr(gpu); return (int)0; } void h3_gpu_profile_set_label(h3_gpu *gpu, const char *label) { h3_cuda_seterr(gpu); } void h3_gpu_profile_mark(h3_gpu *gpu, const char *phase) { h3_cuda_seterr(gpu); } int h3_gpu_linear_f32(h3_gpu *gpu, h3_gpu_tensor *output, const h3_gpu_tensor *input, const h3_gpu_tensor *weight, const h3_gpu_tensor *bias, uint32_t rows, - uint32_t input_dim, uint32_t output_dim) { h3_cuda_seterr(gpu); return 0; } + uint32_t input_dim, uint32_t output_dim) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_patch_linear_bf16(h3_gpu *gpu, h3_gpu_tensor *output, const h3_gpu_tensor *input, const h3_gpu_tensor *weight, const h3_gpu_tensor *bias, uint32_t rows, - uint32_t input_dim, uint32_t output_dim) { h3_cuda_seterr(gpu); return 0; } + uint32_t input_dim, uint32_t output_dim) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_patch_linear_bf16_offset( h3_gpu *gpu, h3_gpu_tensor *output, size_t output_offset, const h3_gpu_tensor *input, size_t input_offset, const h3_gpu_tensor *weight, const h3_gpu_tensor *bias, uint32_t rows, - uint32_t input_dim, uint32_t output_dim) { h3_cuda_seterr(gpu); return 0; } + uint32_t input_dim, uint32_t output_dim) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_patch_linear_bf16_map( h3_gpu *gpu, h3_gpu_tensor *output, const h3_gpu_tensor *input, @@ -120,38 +120,38 @@ int h3_gpu_patch_linear_bf16_map( const h3_gpu_tensor *bias, const h3_gpu_tensor *row_map, uint32_t output_rows, uint32_t rows, - uint32_t input_dim, uint32_t output_dim) { h3_cuda_seterr(gpu); return 0; } + uint32_t input_dim, uint32_t output_dim) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_silu_f32(h3_gpu *gpu, h3_gpu_tensor *output, - const h3_gpu_tensor *input, uint32_t elements) { h3_cuda_seterr(gpu); return 0; } + const h3_gpu_tensor *input, uint32_t elements) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_cast_f32_to_bf16(h3_gpu *gpu, h3_gpu_tensor *output, - const h3_gpu_tensor *input, uint32_t elements) { h3_cuda_seterr(gpu); return 0; } + const h3_gpu_tensor *input, uint32_t elements) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_cast_bf16_to_f32(h3_gpu *gpu, h3_gpu_tensor *output, - const h3_gpu_tensor *input, uint32_t elements) { h3_cuda_seterr(gpu); return 0; } + const h3_gpu_tensor *input, uint32_t elements) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_copy_bf16(h3_gpu *gpu, h3_gpu_tensor *destination, size_t destination_offset, const h3_gpu_tensor *source, size_t source_offset, - size_t elements) { h3_cuda_seterr(gpu); return 0; } + size_t elements) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_copy_f32(h3_gpu *gpu, h3_gpu_tensor *destination, size_t destination_offset, const h3_gpu_tensor *source, size_t source_offset, - size_t elements) { h3_cuda_seterr(gpu); return 0; } + size_t elements) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_rms_norm_f32(h3_gpu *gpu, h3_gpu_tensor *output, const h3_gpu_tensor *input, const h3_gpu_tensor *weight, uint32_t rows, - uint32_t width, float epsilon) { h3_cuda_seterr(gpu); return 0; } + uint32_t width, float epsilon) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_adaln_f32(h3_gpu *gpu, h3_gpu_tensor *output, const h3_gpu_tensor *input, const h3_gpu_tensor *norm_weight, const h3_gpu_tensor *modulation, const h3_gpu_tensor *row_map, uint32_t rows, uint32_t width, uint32_t slots, uint32_t shift_slot, - uint32_t scale_slot, float epsilon) { h3_cuda_seterr(gpu); return 0; } + uint32_t scale_slot, float epsilon) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_gate_f32(h3_gpu *gpu, h3_gpu_tensor *output, const h3_gpu_tensor *residual, const h3_gpu_tensor *branch, const h3_gpu_tensor *modulation, const h3_gpu_tensor *row_map, uint32_t rows, - uint32_t width, uint32_t slots, uint32_t gate_slot) { h3_cuda_seterr(gpu); return 0; } + uint32_t width, uint32_t slots, uint32_t gate_slot) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_qkv_rope_f32(h3_gpu *gpu, h3_gpu_tensor *query, h3_gpu_tensor *key, h3_gpu_tensor *value, const h3_gpu_tensor *qkv, @@ -160,24 +160,24 @@ int h3_gpu_qkv_rope_f32(h3_gpu *gpu, h3_gpu_tensor *query, const h3_gpu_tensor *rope_cos, const h3_gpu_tensor *rope_sin, uint32_t sequence, uint32_t heads, uint32_t head_dim, - uint32_t rope_half, float epsilon) { h3_cuda_seterr(gpu); return 0; } + uint32_t rope_half, float epsilon) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_sdpa_f32(h3_gpu *gpu, h3_gpu_tensor *output, const h3_gpu_tensor *query, const h3_gpu_tensor *key, const h3_gpu_tensor *value, uint32_t sequence, - uint32_t heads, uint32_t head_dim, float scale) { h3_cuda_seterr(gpu); return 0; } + uint32_t heads, uint32_t head_dim, float scale) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_swiglu_f32(h3_gpu *gpu, h3_gpu_tensor *output, const h3_gpu_tensor *fused, uint32_t rows, - uint32_t width) { h3_cuda_seterr(gpu); return 0; } + uint32_t width) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_scale_add_f32(h3_gpu *gpu, h3_gpu_tensor *output, const h3_gpu_tensor *residual, const h3_gpu_tensor *branch, const h3_gpu_tensor *scale, uint32_t rows, - uint32_t width) { h3_cuda_seterr(gpu); return 0; } + uint32_t width) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_layer_norm_f32(h3_gpu *gpu, h3_gpu_tensor *output, const h3_gpu_tensor *input, const h3_gpu_tensor *weight, const h3_gpu_tensor *bias, uint32_t rows, - uint32_t width, float epsilon) { h3_cuda_seterr(gpu); return 0; } + uint32_t width, float epsilon) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_video_qkv_rope_f32(h3_gpu *gpu, h3_gpu_tensor *query, h3_gpu_tensor *key, h3_gpu_tensor *value, const h3_gpu_tensor *qkv, @@ -185,14 +185,14 @@ int h3_gpu_video_qkv_rope_f32(h3_gpu *gpu, h3_gpu_tensor *query, const h3_gpu_tensor *rope_sin, uint32_t sequence, uint32_t heads, uint32_t head_dim, uint32_t rope_half, - float epsilon) { h3_cuda_seterr(gpu); return 0; } + float epsilon) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_conv1d_f32(h3_gpu *gpu, h3_gpu_tensor *output, const h3_gpu_tensor *input, const h3_gpu_tensor *weight, const h3_gpu_tensor *bias, uint32_t batch, uint32_t length, uint32_t input_channels, uint32_t output_channels, uint32_t kernel, - uint32_t padding, uint32_t dilation) { h3_cuda_seterr(gpu); return 0; } + uint32_t padding, uint32_t dilation) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_conv1d_stride_f32(h3_gpu *gpu, h3_gpu_tensor *output, const h3_gpu_tensor *input, const h3_gpu_tensor *weight, @@ -200,7 +200,7 @@ int h3_gpu_conv1d_stride_f32(h3_gpu *gpu, h3_gpu_tensor *output, uint32_t length, uint32_t input_channels, uint32_t output_channels, uint32_t kernel, uint32_t stride, uint32_t padding, - uint32_t dilation) { h3_cuda_seterr(gpu); return 0; } + uint32_t dilation) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_conv_transpose1d_f32( h3_gpu *gpu, h3_gpu_tensor *output, const h3_gpu_tensor *input, @@ -208,15 +208,15 @@ int h3_gpu_conv_transpose1d_f32( const h3_gpu_tensor *bias, uint32_t batch, uint32_t length, uint32_t input_channels, uint32_t output_channels, uint32_t kernel, - uint32_t stride, uint32_t padding) { h3_cuda_seterr(gpu); return 0; } + uint32_t stride, uint32_t padding) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_weight_norm_f32(h3_gpu *gpu, h3_gpu_tensor *output, const h3_gpu_tensor *vector, const h3_gpu_tensor *magnitude, - uint32_t outer, uint32_t inner) { h3_cuda_seterr(gpu); return 0; } + uint32_t outer, uint32_t inner) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_add_scaled_f32(h3_gpu *gpu, h3_gpu_tensor *output, const h3_gpu_tensor *left, const h3_gpu_tensor *right, float left_scale, - float right_scale, uint32_t elements) { h3_cuda_seterr(gpu); return 0; } + float right_scale, uint32_t elements) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_alias_free_snake_f32( h3_gpu *gpu, h3_gpu_tensor *output, const h3_gpu_tensor *input, @@ -225,11 +225,11 @@ int h3_gpu_alias_free_snake_f32( const h3_gpu_tensor *upsample_filter, const h3_gpu_tensor *downsample_filter, uint32_t batch, uint32_t length, - uint32_t channels) { h3_cuda_seterr(gpu); return 0; } + uint32_t channels) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_snake1d_f32(h3_gpu *gpu, h3_gpu_tensor *output, const h3_gpu_tensor *input, const h3_gpu_tensor *alpha, uint32_t batch, - uint32_t length, uint32_t channels) { h3_cuda_seterr(gpu); return 0; } + uint32_t length, uint32_t channels) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_audio_qkv_split_f32(h3_gpu *gpu, h3_gpu_tensor *query, h3_gpu_tensor *key, h3_gpu_tensor *value, const h3_gpu_tensor *qkv, @@ -237,31 +237,31 @@ int h3_gpu_audio_qkv_split_f32(h3_gpu *gpu, const h3_gpu_tensor *k_bias, const h3_gpu_tensor *v_bias, uint32_t batch, uint32_t length, uint32_t heads, - uint32_t head_dim) { h3_cuda_seterr(gpu); return 0; } + uint32_t head_dim) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_sdpa_causal_f32(h3_gpu *gpu, h3_gpu_tensor *output, const h3_gpu_tensor *query, const h3_gpu_tensor *key, const h3_gpu_tensor *value, uint32_t batch, uint32_t sequence, uint32_t heads, - uint32_t head_dim, float scale) { h3_cuda_seterr(gpu); return 0; } + uint32_t head_dim, float scale) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_audio_attention_pool_f32(h3_gpu *gpu, h3_gpu_tensor *output, const h3_gpu_tensor *attended, uint32_t batch, uint32_t length, uint32_t heads, - uint32_t head_dim, uint32_t output_dim) { h3_cuda_seterr(gpu); return 0; } + uint32_t head_dim, uint32_t output_dim) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_geglu_f32(h3_gpu *gpu, h3_gpu_tensor *output, const h3_gpu_tensor *gate, - const h3_gpu_tensor *linear, uint32_t elements) { h3_cuda_seterr(gpu); return 0; } + const h3_gpu_tensor *linear, uint32_t elements) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_clip_f32(h3_gpu *gpu, h3_gpu_tensor *output, const h3_gpu_tensor *input, uint32_t elements, - float minimum, float maximum) { h3_cuda_seterr(gpu); return 0; } + float minimum, float maximum) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_vae_encoder_pad_f32( h3_gpu *gpu, h3_gpu_tensor *output, const h3_gpu_tensor *input, uint32_t batch, uint32_t depth, uint32_t height, uint32_t width, uint32_t channels, uint32_t depth_front, uint32_t height_before, uint32_t height_after, - uint32_t width_before, uint32_t width_after) { h3_cuda_seterr(gpu); return 0; } + uint32_t width_before, uint32_t width_after) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_conv3d_f32(h3_gpu *gpu, h3_gpu_tensor *output, const h3_gpu_tensor *input, const h3_gpu_tensor *weight, @@ -270,36 +270,36 @@ int h3_gpu_conv3d_f32(h3_gpu *gpu, h3_gpu_tensor *output, uint32_t input_channels, uint32_t output_channels, uint32_t kernel_depth, uint32_t kernel_height, uint32_t kernel_width, uint32_t stride_depth, - uint32_t stride_height, uint32_t stride_width) { h3_cuda_seterr(gpu); return 0; } + uint32_t stride_height, uint32_t stride_width) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_vae_encoder_group_norm_silu_f32( h3_gpu *gpu, h3_gpu_tensor *output, const h3_gpu_tensor *input, const h3_gpu_tensor *weight, const h3_gpu_tensor *bias, uint32_t batch, uint32_t depth, uint32_t height, uint32_t width, - uint32_t channels, uint32_t groups, float epsilon) { h3_cuda_seterr(gpu); return 0; } + uint32_t channels, uint32_t groups, float epsilon) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_linear_bf16(h3_gpu *gpu, h3_gpu_tensor *output, const h3_gpu_tensor *input, const h3_gpu_tensor *weight, const h3_gpu_tensor *bias, uint32_t rows, - uint32_t input_dim, uint32_t output_dim) { h3_cuda_seterr(gpu); return 0; } + uint32_t input_dim, uint32_t output_dim) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_mlp_bf16(h3_gpu *gpu, h3_gpu_tensor *output, const h3_gpu_tensor *input, const h3_gpu_tensor *fc1_weight, const h3_gpu_tensor *fc2_weight, uint32_t rows, uint32_t input_dim, uint32_t hidden_dim, - uint32_t output_dim) { h3_cuda_seterr(gpu); return 0; } + uint32_t output_dim) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_mlp_nax_bf16(h3_gpu *gpu, h3_gpu_tensor *output, h3_gpu_tensor *activated, const h3_gpu_tensor *input, const h3_gpu_tensor *fc1_weight, const h3_gpu_tensor *fc2_weight, uint32_t rows, uint32_t input_dim, uint32_t hidden_dim, - uint32_t output_dim) { h3_cuda_seterr(gpu); return 0; } + uint32_t output_dim) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_quantize_weight_int8(h3_gpu *gpu, h3_gpu_tensor *output, h3_gpu_tensor *scales, const h3_gpu_tensor *input, uint32_t rows, - uint32_t columns) { h3_cuda_seterr(gpu); return 0; } + uint32_t columns) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_linear_int8_bf16(h3_gpu *gpu, h3_gpu_tensor *output, h3_gpu_tensor *quantized_input, h3_gpu_tensor *input_scales, @@ -308,7 +308,7 @@ int h3_gpu_linear_int8_bf16(h3_gpu *gpu, h3_gpu_tensor *output, const h3_gpu_tensor *weight_scales, uint32_t rows, uint32_t input_dim, uint32_t output_dim, - int use_slower_uncached_int8_scales) { h3_cuda_seterr(gpu); return 0; } + int use_slower_uncached_int8_scales) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_linear_int8_head_major_bf16( h3_gpu *gpu, h3_gpu_tensor *output, h3_gpu_tensor *quantized_input, @@ -317,7 +317,7 @@ int h3_gpu_linear_int8_head_major_bf16( const h3_gpu_tensor *weight, const h3_gpu_tensor *weight_scales, uint32_t rows, uint32_t heads, - uint32_t head_dim, uint32_t output_dim) { h3_cuda_seterr(gpu); return 0; } + uint32_t head_dim, uint32_t output_dim) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_mlp_int8_bf16(h3_gpu *gpu, h3_gpu_tensor *output, h3_gpu_tensor *activated, h3_gpu_tensor *quantized_activation, @@ -334,21 +334,21 @@ int h3_gpu_mlp_int8_bf16(h3_gpu *gpu, h3_gpu_tensor *output, int use_slower_grouped_quantizer, int use_slower_dynamic_fc1_k, int use_int8_row_fc2, - int input_is_quantized) { h3_cuda_seterr(gpu); return 0; } + int input_is_quantized) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_silu_bf16(h3_gpu *gpu, h3_gpu_tensor *output, - const h3_gpu_tensor *input, uint32_t elements) { h3_cuda_seterr(gpu); return 0; } + const h3_gpu_tensor *input, uint32_t elements) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_rms_norm_bf16(h3_gpu *gpu, h3_gpu_tensor *output, const h3_gpu_tensor *input, const h3_gpu_tensor *weight, uint32_t rows, - uint32_t width, float epsilon) { h3_cuda_seterr(gpu); return 0; } + uint32_t width, float epsilon) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_layer_norm_bf16(h3_gpu *gpu, h3_gpu_tensor *output, const h3_gpu_tensor *input, const h3_gpu_tensor *weight, const h3_gpu_tensor *bias, uint32_t rows, - uint32_t width, float epsilon) { h3_cuda_seterr(gpu); return 0; } + uint32_t width, float epsilon) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_gelu_bf16(h3_gpu *gpu, h3_gpu_tensor *output, const h3_gpu_tensor *input, uint32_t elements, - int approximate) { h3_cuda_seterr(gpu); return 0; } + int approximate) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_vision_qkv_rope_bf16( h3_gpu *gpu, h3_gpu_tensor *query, h3_gpu_tensor *key, h3_gpu_tensor *value, @@ -356,21 +356,21 @@ int h3_gpu_vision_qkv_rope_bf16( const h3_gpu_tensor *rope_cos, const h3_gpu_tensor *rope_sin, uint32_t sequence, uint32_t heads, uint32_t head_dim, - uint32_t rope_half) { h3_cuda_seterr(gpu); return 0; } + uint32_t rope_half) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_adaln_bf16(h3_gpu *gpu, h3_gpu_tensor *output, const h3_gpu_tensor *input, const h3_gpu_tensor *norm_weight, const h3_gpu_tensor *modulation, const h3_gpu_tensor *row_map, uint32_t rows, uint32_t width, uint32_t slots, uint32_t shift_slot, - uint32_t scale_slot, float epsilon) { h3_cuda_seterr(gpu); return 0; } + uint32_t scale_slot, float epsilon) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_adaln_bf16_offset(h3_gpu *gpu, h3_gpu_tensor *output, const h3_gpu_tensor *input, size_t input_offset, const h3_gpu_tensor *norm_weight, const h3_gpu_tensor *modulation, const h3_gpu_tensor *row_map, uint32_t rows, uint32_t width, uint32_t slots, uint32_t shift_slot, - uint32_t scale_slot, float epsilon) { h3_cuda_seterr(gpu); return 0; } + uint32_t scale_slot, float epsilon) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_adaln_linear_bf16( h3_gpu *gpu, h3_gpu_tensor *output, h3_gpu_tensor *inverse, @@ -382,13 +382,13 @@ int h3_gpu_adaln_linear_bf16( const h3_gpu_tensor *bias, uint32_t rows, uint32_t width, uint32_t output_dim, uint32_t slots, uint32_t shift_slot, uint32_t scale_slot, - float epsilon) { h3_cuda_seterr(gpu); return 0; } + float epsilon) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_gate_bf16(h3_gpu *gpu, h3_gpu_tensor *output, const h3_gpu_tensor *residual, const h3_gpu_tensor *branch, const h3_gpu_tensor *modulation, const h3_gpu_tensor *row_map, uint32_t rows, - uint32_t width, uint32_t slots, uint32_t gate_slot) { h3_cuda_seterr(gpu); return 0; } + uint32_t width, uint32_t slots, uint32_t gate_slot) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_gate_adaln_bf16( h3_gpu *gpu, h3_gpu_tensor *gated_residual, h3_gpu_tensor *output, @@ -400,7 +400,7 @@ int h3_gpu_gate_adaln_bf16( const h3_gpu_tensor *row_map, uint32_t rows, uint32_t width, uint32_t slots, uint32_t gate_slot, uint32_t shift_slot, uint32_t scale_slot, - float epsilon) { h3_cuda_seterr(gpu); return 0; } + float epsilon) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_gate_adaln_quantize_int8( h3_gpu *gpu, h3_gpu_tensor *gated_residual, h3_gpu_tensor *quantized_output, @@ -413,7 +413,7 @@ int h3_gpu_gate_adaln_quantize_int8( const h3_gpu_tensor *row_map, uint32_t rows, uint32_t padded_rows, uint32_t width, uint32_t slots, uint32_t gate_slot, uint32_t shift_slot, - uint32_t scale_slot, float epsilon) { h3_cuda_seterr(gpu); return 0; } + uint32_t scale_slot, float epsilon) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_qkv_rope_bf16(h3_gpu *gpu, h3_gpu_tensor *query, h3_gpu_tensor *key, h3_gpu_tensor *value, const h3_gpu_tensor *qkv, @@ -422,7 +422,7 @@ int h3_gpu_qkv_rope_bf16(h3_gpu *gpu, h3_gpu_tensor *query, const h3_gpu_tensor *rope_cos, const h3_gpu_tensor *rope_sin, uint32_t sequence, uint32_t heads, uint32_t head_dim, - uint32_t rope_half, float epsilon) { h3_cuda_seterr(gpu); return 0; } + uint32_t rope_half, float epsilon) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_grouped_qkv_rope_bf16(h3_gpu *gpu, h3_gpu_tensor *query, h3_gpu_tensor *key, h3_gpu_tensor *value, const h3_gpu_tensor *qkv, @@ -432,7 +432,7 @@ int h3_gpu_grouped_qkv_rope_bf16(h3_gpu *gpu, h3_gpu_tensor *query, const h3_gpu_tensor *rope_sin, uint32_t sequence, uint32_t heads, uint32_t head_dim, uint32_t rope_half, - float epsilon) { h3_cuda_seterr(gpu); return 0; } + float epsilon) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_grouped_qkv_linear_rope_bf16( h3_gpu *gpu, h3_gpu_tensor *query, @@ -447,7 +447,7 @@ int h3_gpu_grouped_qkv_linear_rope_bf16( const h3_gpu_tensor *rope_sin, uint32_t rows, uint32_t input_dim, uint32_t heads, uint32_t head_dim, - uint32_t rope_half, float epsilon) { h3_cuda_seterr(gpu); return 0; } + uint32_t rope_half, float epsilon) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_grouped_qkv_linear_rope_int8( h3_gpu *gpu, h3_gpu_tensor *query, @@ -468,23 +468,23 @@ int h3_gpu_grouped_qkv_linear_rope_int8( int input_is_quantized, int use_slower_unfused_qkv_rope, int use_slower_scalar_qkv_rms, - int use_slower_uncached_int8_scales) { h3_cuda_seterr(gpu); return 0; } + int use_slower_uncached_int8_scales) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_sdpa_bf16(h3_gpu *gpu, h3_gpu_tensor *output, const h3_gpu_tensor *query, const h3_gpu_tensor *key, const h3_gpu_tensor *value, uint32_t sequence, - uint32_t heads, uint32_t head_dim, float scale) { h3_cuda_seterr(gpu); return 0; } + uint32_t heads, uint32_t head_dim, float scale) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_sdpa_bf16_head_major_output( h3_gpu *gpu, h3_gpu_tensor *output, const h3_gpu_tensor *query, const h3_gpu_tensor *key, const h3_gpu_tensor *value, uint32_t sequence, - uint32_t heads, uint32_t head_dim, float scale) { h3_cuda_seterr(gpu); return 0; } + uint32_t heads, uint32_t head_dim, float scale) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_swiglu_bf16(h3_gpu *gpu, h3_gpu_tensor *output, const h3_gpu_tensor *fused, uint32_t rows, - uint32_t width) { h3_cuda_seterr(gpu); return 0; } + uint32_t width) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_embedding_bf16(h3_gpu *gpu, h3_gpu_tensor *output, const h3_gpu_tensor *weight, const h3_gpu_tensor *token_ids, uint32_t tokens, - uint32_t vocab_size, uint32_t width) { h3_cuda_seterr(gpu); return 0; } + uint32_t vocab_size, uint32_t width) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_text_qk_rope_bf16(h3_gpu *gpu, h3_gpu_tensor *query_output, h3_gpu_tensor *key_output, @@ -496,30 +496,30 @@ int h3_gpu_text_qk_rope_bf16(h3_gpu *gpu, const h3_gpu_tensor *rope_sin, uint32_t sequence, uint32_t query_heads, uint32_t kv_heads, uint32_t head_dim, - float epsilon) { h3_cuda_seterr(gpu); return 0; } + float epsilon) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_head_rms_norm_bf16(h3_gpu *gpu, h3_gpu_tensor *tensor, const h3_gpu_tensor *weight, uint32_t sequence, uint32_t heads, - uint32_t head_dim, float epsilon) { h3_cuda_seterr(gpu); return 0; } + uint32_t head_dim, float epsilon) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_rope_text_bf16(h3_gpu *gpu, h3_gpu_tensor *query, h3_gpu_tensor *key, const h3_gpu_tensor *rope_cos_f32, const h3_gpu_tensor *rope_sin_f32, uint32_t sequence, uint32_t query_heads, - uint32_t kv_heads, uint32_t head_dim) { h3_cuda_seterr(gpu); return 0; } + uint32_t kv_heads, uint32_t head_dim) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_gqa_causal_bf16(h3_gpu *gpu, h3_gpu_tensor *output, const h3_gpu_tensor *query, const h3_gpu_tensor *key, const h3_gpu_tensor *value, uint32_t sequence, uint32_t query_heads, uint32_t kv_heads, uint32_t head_dim, - float scale) { h3_cuda_seterr(gpu); return 0; } + float scale) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_add_bf16(h3_gpu *gpu, h3_gpu_tensor *output, const h3_gpu_tensor *left, const h3_gpu_tensor *right, - uint32_t elements) { h3_cuda_seterr(gpu); return 0; } + uint32_t elements) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_sub_bf16(h3_gpu *gpu, h3_gpu_tensor *output, const h3_gpu_tensor *left, const h3_gpu_tensor *right, - uint32_t elements) { h3_cuda_seterr(gpu); return 0; } + uint32_t elements) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_token_pool_bf16(h3_gpu *gpu, h3_gpu_tensor *output, const h3_gpu_tensor *input, size_t input_offset, @@ -530,7 +530,7 @@ int h3_gpu_token_pool_bf16(h3_gpu *gpu, h3_gpu_tensor *output, const h3_gpu_tensor *baseline_indices, const h3_gpu_tensor *pairs, uint32_t input_rows, uint32_t rows, uint32_t baseline_rows, - uint32_t width) { h3_cuda_seterr(gpu); return 0; } + uint32_t width) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_token_pool_adaln_bf16( h3_gpu *gpu, h3_gpu_tensor *residual, h3_gpu_tensor *output, @@ -545,7 +545,7 @@ int h3_gpu_token_pool_adaln_bf16( uint32_t input_rows, uint32_t rows, uint32_t baseline_rows, uint32_t width, uint32_t slots, uint32_t shift_slot, - uint32_t scale_slot, float epsilon) { h3_cuda_seterr(gpu); return 0; } + uint32_t scale_slot, float epsilon) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_token_expand_delta_bf16( h3_gpu *gpu, h3_gpu_tensor *output, const h3_gpu_tensor *original, @@ -558,7 +558,7 @@ int h3_gpu_token_expand_delta_bf16( uint32_t reduced_rows, uint32_t baseline_rows, uint32_t width, uint32_t exact_prefix_rows, - float update_scale) { h3_cuda_seterr(gpu); return 0; } + float update_scale) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_token_expand_adaln_bf16( h3_gpu *gpu, h3_gpu_tensor *residual, h3_gpu_tensor *output, @@ -576,11 +576,11 @@ int h3_gpu_token_expand_adaln_bf16( uint32_t baseline_rows, uint32_t width, uint32_t exact_prefix_rows, float update_scale, uint32_t slots, uint32_t shift_slot, - uint32_t scale_slot, float epsilon) { h3_cuda_seterr(gpu); return 0; } + uint32_t scale_slot, float epsilon) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_euler_bf16(h3_gpu *gpu, h3_gpu_tensor *sample, size_t sample_offset, const h3_gpu_tensor *last, const h3_gpu_tensor *previous, uint32_t elements, - float delta, float ratio) { h3_cuda_seterr(gpu); return 0; } + float delta, float ratio) { h3_cuda_seterr(gpu); return (int)0; } int h3_gpu_silu_mul_bf16(h3_gpu *gpu, h3_gpu_tensor *output, const h3_gpu_tensor *gate, - const h3_gpu_tensor *up, uint32_t elements) { h3_cuda_seterr(gpu); return 0; } + const h3_gpu_tensor *up, uint32_t elements) { h3_cuda_seterr(gpu); return (int)0; } From a626261843e5409bfe11f5004241ada045452c0a Mon Sep 17 00:00:00 2001 From: magiodev Date: Wed, 12 Aug 2026 20:59:23 +0000 Subject: [PATCH 4/6] feat/cuda: probe uses cudaDeviceGetAttribute(UnifiedMemory) (CUDA 13 removed prop.unifiedMemory) --- h3_cuda.cu | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/h3_cuda.cu b/h3_cuda.cu index 9440463e..069c729d 100644 --- a/h3_cuda.cu +++ b/h3_cuda.cu @@ -31,7 +31,9 @@ int h3_cuda_probe(h3_device_info *info, char *error, size_t error_size) { snprintf(info->name, sizeof(info->name), "%s", prop.name); snprintf(info->architecture, sizeof(info->architecture), "sm_%d", prop.major * 100 + prop.minor * 10); info->physical_memory = (uint64_t)prop.totalGlobalMem; - info->unified_memory = (prop.unifiedMemory ? 1 : 0); + int unif = 0; + cudaDeviceGetAttribute(&unif, cudaDevAttrUnifiedMemory, 0); + info->unified_memory = (unif ? 1 : 0); } return 1; } From 2e42886455dfd865cfb85def6da7d73fa8e6282c Mon Sep 17 00:00:00 2001 From: magiodev Date: Wed, 12 Aug 2026 21:00:26 +0000 Subject: [PATCH 5/6] feat/cuda: unified_memory=1 (GB10 unified; CUDA13 removed unifiedMemory attr) --- h3_cuda.cu | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/h3_cuda.cu b/h3_cuda.cu index 069c729d..758b934d 100644 --- a/h3_cuda.cu +++ b/h3_cuda.cu @@ -31,9 +31,9 @@ int h3_cuda_probe(h3_device_info *info, char *error, size_t error_size) { snprintf(info->name, sizeof(info->name), "%s", prop.name); snprintf(info->architecture, sizeof(info->architecture), "sm_%d", prop.major * 100 + prop.minor * 10); info->physical_memory = (uint64_t)prop.totalGlobalMem; - int unif = 0; - cudaDeviceGetAttribute(&unif, cudaDevAttrUnifiedMemory, 0); - info->unified_memory = (unif ? 1 : 0); + /* GB10/DGX Spark is a unified-memory architecture (CUDA 13 removed + * both prop.unifiedMemory and cudaDevAttrUnifiedMemory). */ + info->unified_memory = 1; } return 1; } From 65c8ac31dcae686c6447c0ad9cb701b73aff4fad Mon Sep 17 00:00:00 2001 From: magiodev Date: Wed, 12 Aug 2026 21:10:21 +0000 Subject: [PATCH 6/6] feat/cuda: extern "C" guards in h3_gpu.h/h3_cuda.h + include h3_cuda.h in h3_cuda.cu nvcc compiles .cu as C++; without C linkage the GPU API symbols were mangled and the host C objects could not link. extern "C" guards are compile-time only and inert for the Metal build (.c/.m never define __cplusplus). --- h3_cuda.cu | 1 + h3_cuda.h | 8 ++++++++ h3_gpu.h | 8 ++++++++ 3 files changed, 17 insertions(+) diff --git a/h3_cuda.cu b/h3_cuda.cu index 758b934d..b2637377 100644 --- a/h3_cuda.cu +++ b/h3_cuda.cu @@ -10,6 +10,7 @@ #include #include "h3_gpu.h" #include "h3.h" +#include "h3_cuda.h" #define H3_CUDA_ERR "CUDA backend: op not yet implemented (feat/cuda)" diff --git a/h3_cuda.h b/h3_cuda.h index f5eb09ee..955171cf 100644 --- a/h3_cuda.h +++ b/h3_cuda.h @@ -3,6 +3,14 @@ #include "h3.h" +#ifdef __cplusplus +extern "C" { +#endif + int h3_cuda_probe(h3_device_info *info, char *error, size_t error_size); +#ifdef __cplusplus +} +#endif + #endif diff --git a/h3_gpu.h b/h3_gpu.h index 3a47cc35..2f1db0f0 100644 --- a/h3_gpu.h +++ b/h3_gpu.h @@ -1,6 +1,10 @@ #ifndef H3_GPU_H #define H3_GPU_H +#ifdef __cplusplus +extern "C" { +#endif + #include #include @@ -610,4 +614,8 @@ int h3_gpu_silu_mul_bf16(h3_gpu *gpu, h3_gpu_tensor *output, const h3_gpu_tensor *gate, const h3_gpu_tensor *up, uint32_t elements); +#ifdef __cplusplus +} +#endif + #endif