# Compiler and flags CC := g++ CXXFLAGS := -std=c++14 -Wall -Iinclude -O3 -march=native -fopenmp LDFLAGS := -fopenmp # Compiles .h files when there's been a change DEPFLAGS := -MMD -MP CXX ?= g++ # Directories SRC_DIR := src INC_DIR := include OBJ_DIR := obj BIN_DIR := bin TEST_BIN := $(BIN_DIR)/tests # # === Executable Name === TARGET := $(BIN_DIR)/abc_lab # === Find all .cpp files recursively in src/ === SRCS := $(shell find $(SRC_DIR) -name '*.cpp') # === Convert src/foo/bar.cpp → obj/foo/bar.o === OBJS := $(patsubst $(SRC_DIR)/%.cpp,$(OBJ_DIR)/%.o,$(SRCS)) # === Test sources === TEST_SRCS := $(shell find test -name 'test_*.cpp') TEST_OBJS := $(patsubst test/%.cpp, $(OBJ_DIR)/test/%.o, $(TEST_SRCS)) # Compiles .h files when there's been a change DEPS := $(OBJS:.o=.d) $(TEST_OBJS:.o=.d) $(TEST_MAIN:.o=.d) -include $(DEPS) # The single file that defines TEST_MAIN / main() TEST_MAIN := $(OBJ_DIR)/test/test_all.o # === OpenMP runtime configuration (override-able) === OMP_PROC_BIND ?= close # close|spread|master OMP_PLACES ?= cores # cores|threads|sockets OMP_MAX_LEVELS ?= 1 # 1 = no nested teams; set 2+ to allow nesting OMP_THREADS ?= 16 # e.g. "16" or "8,4" for nested (outer,inner) OMP_DYNAMIC ?= TRUE # TRUE/FALSE: let runtime adjust threads OMP_SCHEDULE ?= STATIC # STATIC recommended for matvec/matmul OMP_DISPLAY_ENV ?= FALSE # TRUE to print runtime config at startup # Export OMP defaults so child makes or tools see them (not strictly required) export OMP_PROC_BIND export OMP_PLACES export OMP_MAX_LEVELS export OMP_THREADS export OMP_DYNAMIC export OMP_SCHEDULE export OMP_DISPLAY_ENV # What belongs to "run" vs "test" RUN_DEPS := $(OBJS:.o=.d) TEST_DEPS := $(TEST_OBJS:.o=.d) $(TEST_MAIN:.o=.d) RUN_ARTIFACTS := $(TARGET) $(OBJS) $(RUN_DEPS) TEST_ARTIFACTS := $(TEST_BIN) $(TEST_OBJS) $(TEST_MAIN) $(TEST_DEPS) # === Default Target === all: $(TARGET) # === Linking final executable === $(TARGET): $(OBJS) @mkdir -p $(dir $@) $(CXX) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) # === Compiling source files to object files === $(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp @mkdir -p $(dir $@) $(CXX) $(CXXFLAGS) $(DEPFLAGS) -c $< -o $@ # === Run with OpenMP env set only for the run === .PHONY: run run: clean-test $(TARGET) @echo ">>> OMP_PROC_BIND=$(OMP_PROC_BIND)" @echo ">>> OMP_PLACES=$(OMP_PLACES)" @echo ">>> OMP_MAX_ACTIVE_LEVELS=$(OMP_MAX_LEVELS)" @echo ">>> OMP_NUM_THREADS=$(OMP_THREADS)" @echo ">>> OMP_DYNAMIC=$(OMP_DYNAMIC)" @echo ">>> OMP_SCHEDULE=$(OMP_SCHEDULE)" @echo ">>> OMP_DISPLAY_ENV=$(OMP_DISPLAY_ENV)" @OMP_PROC_BIND=$(OMP_PROC_BIND) \ OMP_PLACES=$(OMP_PLACES) \ OMP_MAX_ACTIVE_LEVELS=$(OMP_MAX_LEVELS) \ OMP_NUM_THREADS="$(OMP_THREADS)" \ OMP_DYNAMIC=$(OMP_DYNAMIC) \ OMP_SCHEDULE=$(OMP_SCHEDULE) \ OMP_DISPLAY_ENV=$(OMP_DISPLAY_ENV) \ ./$(TARGET) # Handy presets .PHONY: run-single-core run-single-core: ## Single-level one core (good default) $(MAKE) run OMP_MAX_LEVELS=1 OMP_THREADS=1 OMP_PROC_BIND=close OMP_PLACES=cores # Handy presets .PHONY: run-multi-core run-multi-core: ## Single-level parallel (good default) $(MAKE) run OMP_MAX_LEVELS=1 OMP_THREADS=16 OMP_PROC_BIND=close OMP_PLACES=cores .PHONY: run-nested-multi-core run-nested-multi-core: ## Two-level nested (outer,inner), adjust to your cores $(MAKE) run OMP_MAX_LEVELS=2 OMP_THREADS="2,8" OMP_PROC_BIND=close OMP_PLACES=cores # Optional: print debug info .PHONY: info info: @echo "Source files: $(SRCS)" @echo "Object files: $(OBJS)" @echo "CXXFLAGS: $(CXXFLAGS)" @echo "LDFLAGS: $(LDFLAGS)" .PHONY: test test: clean-run $(TEST_BIN) @echo ">>> OMP_PROC_BIND=$(OMP_PROC_BIND)" @echo ">>> OMP_PLACES=$(OMP_PLACES)" @echo ">>> OMP_MAX_ACTIVE_LEVELS=$(OMP_MAX_LEVELS)" @echo ">>> OMP_NUM_THREADS=$(OMP_THREADS)" @echo ">>> OMP_DYNAMIC=$(OMP_DYNAMIC)" @echo ">>> OMP_SCHEDULE=$(OMP_SCHEDULE)" @echo ">>> OMP_DISPLAY_ENV=$(OMP_DISPLAY_ENV)" @OMP_PROC_BIND=$(OMP_PROC_BIND) \ OMP_PLACES=$(OMP_PLACES) \ OMP_MAX_ACTIVE_LEVELS=$(OMP_MAX_LEVELS) \ OMP_NUM_THREADS="$(OMP_THREADS)" \ OMP_DYNAMIC=$(OMP_DYNAMIC) \ OMP_SCHEDULE=$(OMP_SCHEDULE) \ OMP_DISPLAY_ENV=$(OMP_DISPLAY_ENV) \ $(TEST_BIN) $(TEST_BIN): $(TEST_OBJS) $(TEST_MAIN) @mkdir -p $(BIN_DIR) $(CXX) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) $(OBJ_DIR)/test/%.o: test/%.cpp @mkdir -p $(dir $@) $(CXX) $(CXXFLAGS) $(DEPFLAGS) -c $< -o $@ # Clean up .PHONY: clean clean: rm -rf $(OBJ_DIR) $(BIN_DIR) .PHONY: clean-run clean-test clean-run: @echo "Cleaning run artifacts..." @rm -f $(RUN_ARTIFACTS) clean-test: @echo "Cleaning test artifacts..." @rm -f $(TEST_ARTIFACTS)