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
45 changes: 42 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,10 @@

name: tests

# Direct pushes to the default branch (covers both common names), plus all PRs.
# If your default branch is named something else, add it to the push list.
# Direct pushes to any branch, plus all PRs. Branch pushes let fork/feature
# branches produce CI evidence even while an upstream PR waits for approval.
on:
push:
branches: [main, master]
pull_request:

jobs:
Expand Down Expand Up @@ -58,3 +57,43 @@ jobs:
echo "API_QUICKREF.md is out of date -- run 'python apiquickref.py' and commit the result.";
exit 1;
}

c-kernel-evidence:
runs-on: ubuntu-latest
timeout-minutes: 15

env:
MPLBACKEND: Agg

steps:
- name: Check out the code
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
cache: pip

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt

- name: Compile, test, and benchmark the C kernel
run: |
python c/benchmarks/ci_evidence.py --output-dir c/build/ci-evidence

- name: Publish C kernel evidence summary
if: always()
run: |
if [ -f c/build/ci-evidence/report.md ]; then
cat c/build/ci-evidence/report.md >> "$GITHUB_STEP_SUMMARY"
fi

- name: Upload C kernel evidence artifact
if: always()
uses: actions/upload-artifact@v4
with:
name: c-kernel-evidence
path: c/build/ci-evidence/
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/.venv
/__pycache__
__pycache__/
/metrics/
holostuff.zip
109 changes: 109 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
PYTHON ?= python3
PYTEST ?= $(PYTHON) -m pytest

UNAME_S := $(shell uname -s)
DEFAULT_HOLO_USE_ACCELERATE := 0
ifeq ($(UNAME_S),Darwin)
DEFAULT_HOLO_USE_ACCELERATE := 1
endif
HOLO_USE_ACCELERATE ?= $(DEFAULT_HOLO_USE_ACCELERATE)

C_MAKE := $(MAKE) -C c HOLO_USE_ACCELERATE=$(HOLO_USE_ACCELERATE) PYTHON=$(PYTHON)
C_ENV := HOLOSTUFF_USE_C=1 HOLOSTUFF_C_STRICT=1

.PHONY: help all deps check-experiment-deps c c-test c-bench c-ci-evidence sokol-asteroids sokol-run test test-py benchmark benchmark-c ablations ablations-c stress stress-c metrics metrics-c-tests metrics-path-d metrics-full experiments experiments-c demos clean

help:
@printf '%s\n' \
'Targets:' \
' make c build the C kernel shared/static library' \
' make c-test run C kernel tests' \
' make c-bench compare Python/NumPy vs C trace, bind_fixed, and VSA program kernels' \
' make c-ci-evidence compile CI evidence that scalar C trace beats NumPy' \
' make sokol-asteroids build the real-time Sokol asteroid-belt renderer' \
' make sokol-run build and run the Sokol asteroid-belt renderer' \
' make deps install base + experiment Python dependencies' \
' make test build C kernel, then run pytest' \
' make benchmark run benchmark_holographic.py with NumPy core' \
' make benchmark-c run benchmark_holographic.py with C core' \
' make metrics write central JSON/Markdown metrics evidence' \
' make metrics-c-tests run selected tests with NumPy and C-kernel modes, then write metrics evidence' \
' make metrics-path-d regenerate core Path D caches, then write metrics evidence' \
' make metrics-full run full ablations, stress, Path D, and strict metrics evidence' \
' make experiments run benchmark, ablations, and stress with NumPy core' \
' make experiments-c run benchmark, ablations, stress, and trace bench with C core' \
' make demos run the guided tour'

all: c

deps:
$(PYTHON) -m pip install -r requirements.txt -r requirements-experiments.txt

check-experiment-deps:
@$(PYTHON) -c "import importlib.util, sys; missing = [m for m in ('matplotlib', 'pandas', 'scipy', 'sklearn') if importlib.util.find_spec(m) is None]; print('Missing experiment dependencies: ' + ', '.join(missing)) if missing else None; sys.exit(1 if missing else 0)" || \
(echo "Missing experiment dependencies; run: make deps PYTHON=$(PYTHON)" && exit 1)

c:
$(C_MAKE) all

c-test:
$(C_MAKE) test

c-bench:
$(C_MAKE) bench-compare

c-ci-evidence:
$(PYTHON) c/benchmarks/ci_evidence.py

sokol-asteroids:
$(C_MAKE) sokol-asteroids

sokol-run:
$(C_MAKE) sokol-run

test: c
$(PYTEST)

test-py:
$(PYTEST)

benchmark: check-experiment-deps
$(PYTHON) benchmark_holographic.py

benchmark-c: c check-experiment-deps
$(C_ENV) $(PYTHON) benchmark_holographic.py

ablations:
$(PYTHON) holographic_ablate.py

ablations-c: c
$(C_ENV) $(PYTHON) holographic_ablate.py

stress:
$(PYTHON) stress_holographic.py

stress-c: c
$(C_ENV) $(PYTHON) stress_holographic.py

metrics:
$(PYTHON) holographic_metrics.py --output-dir metrics

metrics-c-tests: c
$(PYTHON) holographic_metrics.py --output-dir metrics --run-c-mode-tests

metrics-path-d:
$(PYTHON) holographic_metrics.py --output-dir metrics --run-path-d

metrics-full:
$(PYTHON) holographic_metrics.py --output-dir metrics --full-ablations --include-stress --run-path-d all --strict

experiments: benchmark ablations stress

experiments-c: c benchmark-c ablations-c stress-c c-bench

demos:
$(PYTHON) tour.py

clean:
$(C_MAKE) clean
rm -f benchmark_report.md bench_*.png
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,9 @@ Like leOS, leCore is **free and open source**, and the work that keeps it free i
- **`THEORY.md`** — the load-bearing claims and what backs each one (the honest middle ground, not a paper).
- **`NOTES_concepts.md`** — the running design log: what was tried, what worked, what didn't.
- **`ISA.md`** — the small instruction set the engine's programs are built from.
- **`holographic_metrics.py`** — the central JSON/Markdown evidence rollup; run `make metrics` for fast
evidence, `make metrics-c-tests` for NumPy/C mode parity, or `make metrics-path-d` to refresh the core
Path D caches first.
- The module docstrings — every `holographic_*.py` file opens with a plain-language "why this exists" (and
those are exactly what `REFERENCE.md` gathers up for you).

Expand Down
1 change: 1 addition & 0 deletions c/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
build/
109 changes: 109 additions & 0 deletions c/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
CC ?= cc
AR ?= ar
PYTHON ?= python3
HOLO_USE_ACCELERATE ?= 0
UNAME_S := $(shell uname -s)

BUILD_FLAVOR := scalar
ifeq ($(HOLO_USE_ACCELERATE),1)
BUILD_FLAVOR := accelerate
CPPFLAGS += -DHOLO_USE_ACCELERATE=1
LDLIBS += -framework Accelerate
endif

BUILD_DIR := build/$(BUILD_FLAVOR)
SOKOL_DIR ?= ../vendor/sokol
SOKOL_BUILD_DIR := build/sokol
SOKOL_ASTEROIDS := $(SOKOL_BUILD_DIR)/holo_sokol_asteroids
INCLUDE_DIR := include
SRC_DIR := src
TEST_DIR := tests
BENCH_DIR := benchmarks

THREAD_FLAGS ?= -pthread
CFLAGS ?= -std=c99 -O3 -Wall -Wextra -Wpedantic
CFLAGS += $(THREAD_FLAGS)
PICFLAGS ?= -fPIC
CPPFLAGS += -I$(INCLUDE_DIR)
LDLIBS += $(THREAD_FLAGS) -lm

ifeq ($(UNAME_S),Darwin)
SHLIB_EXT := .dylib
SHLIB_FLAGS := -dynamiclib -install_name @rpath/libholoc$(SHLIB_EXT)
SOKOL_SOURCE_MODE := -x objective-c
SOKOL_LDLIBS := -framework Cocoa -framework QuartzCore -framework OpenGL
else
SHLIB_EXT := .so
SHLIB_FLAGS := -shared
SOKOL_SOURCE_MODE :=
SOKOL_LDLIBS := -lX11 -lXi -lXcursor -lGL -ldl -lpthread -lm
endif

LIB := $(BUILD_DIR)/libholoc.a
SHLIB := $(BUILD_DIR)/libholoc$(SHLIB_EXT)
OBJS := $(BUILD_DIR)/holo_core.o $(BUILD_DIR)/holo_trace.o $(BUILD_DIR)/holo_program.o
TESTS := $(BUILD_DIR)/test_core $(BUILD_DIR)/test_trace $(BUILD_DIR)/test_program
BENCHES := $(BUILD_DIR)/bench_trace

.PHONY: all shared test bench bench-fixed bench-program bench-compare sokol-asteroids sokol-run clean

all: $(LIB) $(SHLIB)

shared: $(SHLIB)

$(BUILD_DIR):
mkdir -p $(BUILD_DIR)

$(SOKOL_BUILD_DIR):
mkdir -p $(SOKOL_BUILD_DIR)

$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c | $(BUILD_DIR)
$(CC) $(CPPFLAGS) $(CFLAGS) $(PICFLAGS) -c $< -o $@

$(LIB): $(OBJS)
$(AR) rcs $@ $^

$(SHLIB): $(OBJS)
$(CC) $(SHLIB_FLAGS) $^ $(LDLIBS) -o $@

$(BUILD_DIR)/test_core: $(TEST_DIR)/test_core.c $(LIB)
$(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDLIBS) -o $@

$(BUILD_DIR)/test_trace: $(TEST_DIR)/test_trace.c $(LIB)
$(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDLIBS) -o $@

$(BUILD_DIR)/test_program: $(TEST_DIR)/test_program.c $(LIB)
$(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDLIBS) -o $@

$(BUILD_DIR)/bench_trace: $(BENCH_DIR)/bench_trace.c $(LIB)
$(CC) $(CPPFLAGS) $(CFLAGS) $< $(LIB) $(LDLIBS) -o $@

test: $(TESTS)
./$(BUILD_DIR)/test_core
./$(BUILD_DIR)/test_trace
./$(BUILD_DIR)/test_program

bench: $(BENCHES)
./$(BUILD_DIR)/bench_trace

bench-fixed: $(SHLIB)
HOLOSTUFF_C_LIB=$(abspath $(SHLIB)) $(PYTHON) benchmarks/bench_bind_fixed.py --summary

bench-program: $(SHLIB)
HOLOSTUFF_C_LIB=$(abspath $(SHLIB)) $(PYTHON) benchmarks/bench_program.py --summary

bench-compare: $(BENCHES) $(SHLIB)
$(PYTHON) benchmarks/bench_trace.py --summary --binary ./$(BUILD_DIR)/bench_trace
HOLOSTUFF_C_LIB=$(abspath $(SHLIB)) $(PYTHON) benchmarks/bench_bind_fixed.py --summary
HOLOSTUFF_C_LIB=$(abspath $(SHLIB)) $(PYTHON) benchmarks/bench_program.py --summary

sokol-asteroids: $(SOKOL_ASTEROIDS)

sokol-run: $(SOKOL_ASTEROIDS)
./$(SOKOL_ASTEROIDS)

$(SOKOL_ASTEROIDS): sokol/holo_sokol_asteroids.c $(SOKOL_DIR)/sokol_app.h $(SOKOL_DIR)/sokol_gfx.h $(SOKOL_DIR)/sokol_glue.h $(SOKOL_DIR)/sokol_log.h | $(SOKOL_BUILD_DIR)
$(CC) $(SOKOL_SOURCE_MODE) $(CPPFLAGS) -I$(SOKOL_DIR) $(CFLAGS) $< $(SOKOL_LDLIBS) -o $@

clean:
rm -rf build
Loading