Files
LithosAnanake/include/physics_pipelining_metrics.h
T

431 lines
16 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
StarForth — Steady-State Virtual Machine Runtime
Copyright (c) 20232025 Robert A. James
All rights reserved.
This file is part of the StarForth project.
Licensed under the StarForth License, Version 1.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at:
https://github.com/star.4th@proton.me/StarForth/LICENSE.txt
This software is provided "AS IS", WITHOUT WARRANTY OF ANY KIND,
express or implied, including but not limited to the warranties of
merchantability, fitness for a particular purpose, and noninfringement.
See the License for the specific language governing permissions and
limitations under the License.
StarForth — Steady-State Virtual Machine Runtime
Copyright (c) 20232025 Robert A. James
All rights reserved.
This file is part of the StarForth project.
Licensed under the StarForth License, Version 1.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at:
https://github.com/star.4th@proton.me/StarForth/LICENSE.txt
This software is provided "AS IS", WITHOUT WARRANTY OF ANY KIND,
express or implied, including but not limited to the warranties of
merchantability, fitness for a particular purpose, and noninfringement.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
*** StarForth ***
physics_pipelining_metrics.h - Word transition tracking for speculative execution
Phase 1: Instrumentation for pipelining/speculative execution
This module tracks word-to-word transitions (frequency of which words follow
which other words) to support speculative prefetching and pipelining decisions.
Terminology:
- transition_heat[i]: How many times word[i] has been executed immediately
after this word (forms prediction basis)
- total_transitions: Sum of all transition_heat entries
- prefetch_*: Metrics for speculative execution success/failure
*/
#ifndef PHYSICS_PIPELINING_METRICS_H
#define PHYSICS_PIPELINING_METRICS_H
#include <stdint.h>
#include "starforth_config.h"
/* ============================================================================
* Pipelining Feature Switch (disabled by default during Phase 1)
* ============================================================================
* Default lives in starforth_config.h, the single source of truth for VM
* build-time defaults; overridable via -D exactly as before.
*/
/* ============================================================================
* Tuning Knobs (adjustable at compile-time, future: runtime)
* ============================================================================
*/
/**
* SPECULATION_THRESHOLD_Q48: Minimum probability (Q48.16) to speculate on
* a word transition.
* Range: 0.10 (very aggressive) to 0.95 (very conservative)
* Default: see starforth_config.h (STARFORTH_CONFIG_SPECULATION_THRESHOLD_Q48_DEFAULT)
* Q48.16 encoding: 0.50 = 0x8000LL (1LL << 15)
*/
/**
* SPECULATION_DEPTH: How many words ahead to prefetch speculatively.
* Range: 1 (next word only) to 4 (very aggressive)
* Default: see starforth_config.h (STARFORTH_CONFIG_SPECULATION_DEPTH_DEFAULT)
*/
/**
* MIN_SAMPLES_FOR_SPECULATION: Minimum number of transitions observed
* before making speculation decisions.
* Range: 1 (immediate) to 100 (very conservative)
* Default: see starforth_config.h (STARFORTH_CONFIG_MIN_SAMPLES_FOR_SPECULATION_DEFAULT)
*/
/**
* MISPREDICTION_COST_Q48: Estimated cost (in nanoseconds, Q48.16 format)
* of recovering from wrong speculation.
* This is calibrated to the actual recovery time on target hardware.
* Range: 0 to 100 ns
* Default: see starforth_config.h (STARFORTH_CONFIG_MISPREDICTION_COST_Q48_DEFAULT)
* Q48.16 encoding: 25 ns = 25 << 16 = 0x190000LL
*/
/**
* MINIMUM_PREFETCH_ROI: Minimum expected Return-On-Investment ratio
* for speculation to be worthwhile.
* Speculation succeeds only if:
* (prefetch_latency_saved / total_attempts) > MINIMUM_PREFETCH_ROI
* Range: 1.0 (always speculate) to 2.0 (very selective)
* Default: see starforth_config.h (STARFORTH_CONFIG_MINIMUM_PREFETCH_ROI_DEFAULT)
* Q48.16 encoding: 1.10 = 1.10 * (1 << 16) = 0x1199AL
*/
/**
* TRANSITION_WINDOW_SIZE: Knob #6 - Execution context depth for prediction
*
* How many previous words to remember when predicting next word.
* Larger window captures deeper patterns but uses more memory.
*
* Window=1: Only immediate predecessor (A→B predictions)
* Window=2: Previous 2 words (A,B→C predictions) - good balance
* Window=4: Previous 4 words (captures multi-level patterns)
* Window=8: Very deep, expensive -- see starforth_config.h for the actual
* shipped default
*
* Binary Chop Search Space (Phase 2):
* Iteration 1: Try window=2 (baseline)
* Iteration 2: Try window=1 and window=4
* Iteration 3: Narrow to optimal (1, 2, or 4)
* Converge: Pick size with highest prediction accuracy
*
* Range: 1 to 8
* Default: see starforth_config.h (STARFORTH_CONFIG_TRANSITION_WINDOW_SIZE_DEFAULT)
* Trade-off: Pattern depth vs. memory usage & complexity
*
* Tuning: make TRANSITION_WINDOW_SIZE=1 (or 2, 4, 8)
*/
/* ============================================================================
* Word Transition Metrics
* ============================================================================
*
* Allocated per dictionary entry to track which words follow this word.
* This is the basis for speculative prefetching decisions.
*/
typedef struct WordTransitionMetrics {
/**
* transition_heat[i]: Number of times word with index i has been
* executed immediately after this word.
*
* Dynamically allocated array of size DICTIONARY_SIZE.
* Initialized to NULL; allocated on first use to save memory
* for words that are never executed.
*/
uint64_t *transition_heat;
/** Total number of transitions observed from this word */
uint64_t total_transitions;
/** Number of speculative prefetch attempts made for this word */
uint64_t prefetch_attempts;
/** Number of successful prefetch predictions (hits) */
uint64_t prefetch_hits;
/** Number of failed prefetch predictions (misses) */
uint64_t prefetch_misses;
/**
* Total latency saved through successful prefetching (Q48.16 nanoseconds).
* Positive value indicates net benefit from speculation.
*/
int64_t prefetch_latency_saved_q48;
/**
* Total latency cost from failed prefetch predictions (Q48.16 nanoseconds).
* Negative value (cost) to be subtracted from savings.
*/
int64_t misprediction_cost_q48;
/**
* Cached probability of most likely next word (for quick access).
* Updated periodically to avoid recomputation.
* Q48.16 format (0.0 to 1.0 == 0LL to 1LL<<16)
*/
int64_t max_transition_probability_q48;
/**
* Index (word id) of most likely next word.
* Used for fast prefetch without scanning transition_heat array.
*/
uint32_t most_likely_next_word_id;
/* ========== Context-Aware Transitions (Phase 1 Extension) ========== */
/**
* Circular buffer of previous word IDs for context tracking.
* Size = TRANSITION_WINDOW_SIZE (default 2)
* Used to build multi-word context patterns (e.g., A,B→C)
*
* Example with WINDOW=2:
* context_window[0] = older word (2 steps back)
* context_window[1] = recent word (1 step back)
* Next word completes the pattern: (context_window[0], context_window[1]) → next
*/
uint32_t *context_window;
/**
* Current position in context_window circular buffer.
* Points to slot where next word ID will be stored.
*/
uint32_t context_window_pos;
/**
* Sparse hash table for context-based transitions.
* Maps: hash(context_window) → counts_array[DICTIONARY_SIZE]
*
* Phase 1: Collect only (simple reference implementation)
* Phase 2: Analyze prediction accuracy by context depth
* Phase 3: Use for adaptive prefetching decisions
*
* Opaque pointer - implementation is in transition_metrics.c
*/
void *context_transitions;
/**
* Total context-based transitions observed.
* Counter for Phase 2 analysis (accuracy measurement)
*/
uint64_t total_context_transitions;
/**
* Actual window size for this word's metrics.
* May differ from TRANSITION_WINDOW_SIZE if memory allocation failed.
* Phase 2 uses this to validate context data reliability.
*/
uint32_t actual_window_size;
} WordTransitionMetrics;
/* ============================================================================
* Transition Metrics API
* ============================================================================
*/
/*
* Initialize word transition metrics for a dictionary entry.
* Called once per word during dictionary entry creation.
*
* @param metrics Pointer to uninitialized WordTransitionMetrics
* @return 0 on success, -1 on memory allocation failure
*/
int transition_metrics_init(WordTransitionMetrics *metrics);
/*
* Record a word transition (word_from -> word_to).
* Called in the inner interpreter after each word execution.
*
* @param metrics Metrics for the current word
* @param next_word_id Index of word that executed next
* @param dict_size Total number of words in dictionary (for array bounds)
* @return 0 on success, -1 on invalid word_id
*/
int transition_metrics_record(WordTransitionMetrics *metrics, uint32_t next_word_id, uint32_t dict_size);
/*
* Get the probability (Q48.16 format) of a specific word following this word.
*
* Returns: (transition_heat[target] / total_transitions) in Q48.16 format
* or 0 if total_transitions == 0
*
* @param metrics Metrics for the current word
* @param target_word_id Index of potential next word
* @return Probability in Q48.16 format (0.0 to 1.0)
*/
int64_t transition_metrics_get_probability_q48(const WordTransitionMetrics *metrics, uint32_t target_word_id);
/*
* Update cached most-likely-next-word information.
* Should be called periodically (e.g., after every 100 transitions)
* to avoid stale cache.
*
* @param metrics Metrics for the current word
* @param dict_size Total number of words in dictionary
*/
void transition_metrics_update_cache(WordTransitionMetrics *metrics, uint32_t dict_size);
/*
* Record a successful prefetch prediction.
* Called when speculation correctly predicted the next word.
*
* @param metrics Metrics for the current word
* @param latency_saved_ns Nanoseconds saved (will be Q48.16 encoded)
*/
void transition_metrics_record_prefetch_hit(WordTransitionMetrics *metrics, int64_t latency_saved_ns);
/*
* Record a failed prefetch prediction.
* Called when speculation incorrectly predicted the next word.
*
* @param metrics Metrics for the current word
* @param recovery_cost_ns Nanoseconds lost to misprediction recovery
*/
void transition_metrics_record_prefetch_miss(WordTransitionMetrics *metrics, int64_t recovery_cost_ns);
/*
* Check if speculation should be attempted for a given target word.
* Applies threshold logic and ROI analysis.
*
* Returns: 1 if speculation should be attempted, 0 otherwise
*
* @param metrics Metrics for the current word
* @param target_word_id Index of potential next word
* @return 1 if probability > SPECULATION_THRESHOLD and enough samples, 0 otherwise
*/
int transition_metrics_should_speculate(const WordTransitionMetrics *metrics, uint32_t target_word_id);
/*
* Get detailed statistics string for diagnostics.
* Caller must free the returned string.
*
* @param metrics Metrics to report on
* @return Formatted statistics string (must be freed by caller)
*/
char *transition_metrics_stats_string(const WordTransitionMetrics *metrics);
/*
* Reset all transition metrics (clear counts, free transition_heat array).
* Called on VM reset or explicit metrics reset.
*
* @param metrics Metrics to reset
*/
void transition_metrics_reset(WordTransitionMetrics *metrics);
/*
* Free all allocated memory for transition metrics.
* Called during dictionary cleanup.
*
* @param metrics Metrics to clean up
*/
void transition_metrics_cleanup(WordTransitionMetrics *metrics);
/* ============================================================================
* Context-Aware Transition API (Phase 1 Extension)
* ============================================================================
*
* These functions handle multi-word pattern tracking for Phase 2 analysis.
* Phase 1: Collect context window data (this session)
* Phase 2: Analyze accuracy by context depth (next session)
* Phase 3: Use for adaptive prediction (future)
*/
/*
* Record a context-based transition (multi-word pattern).
* Called after each word execution with the execution window.
*
* Example with WINDOW=2:
* context[0] = word_A, context[1] = word_B, next_word = word_C
* Records: (A,B) → C transition in sparse hash table
*
* Phase 1: Just collects data, no analysis
* Phase 2: Will measure: "Do patterns with window=2 predict better than window=1?"
*
* @param metrics Metrics for the current word
* @param context Array of word IDs forming the context (size = window_size)
* @param window_size Length of context array
* @param next_word_id Word that follows the context
* @param dict_size Total number of words in dictionary
* @return 0 on success, -1 on error
*/
int transition_metrics_record_context(WordTransitionMetrics *metrics,
const uint32_t *context,
uint32_t window_size,
uint32_t next_word_id,
uint32_t dict_size);
/*
* Update the execution context window with a new word.
* Called after each word execution to slide the window forward.
*
* Example with WINDOW=2:
* Before: [A, B] (two previous words)
* After calling with C: [B, C] (shift left, add C on right)
*
* @param metrics Metrics to update
* @param word_id New word ID to add to window
* @return 0 on success, -1 if context tracking not initialized
*/
int transition_metrics_update_context_window(WordTransitionMetrics *metrics, uint32_t word_id);
/*
* Get context-based prediction accuracy statistics (Phase 2).
* Compares prediction success rates across different window sizes.
*
* Phase 2 will use this to run binary chop tuning:
* Measure accuracy(window=1), accuracy(window=2), accuracy(window=4)
* Binary search converges to optimal window size
*
* @param metrics Metrics to analyze
* @return Formatted string with accuracy statistics (caller must free)
*/
char *transition_metrics_context_accuracy_string(const WordTransitionMetrics *metrics);
/*
* Get recommended window size based on collected data.
* Phase 2 will call this as part of binary chop tuning algorithm.
*
* Algorithm:
* 1. Collect data with current window size
* 2. Measure prediction accuracy
* 3. If accuracy improves, try larger window
* 4. If accuracy declines, try smaller window
* 5. Converge to optimal size
*
* @param metrics Metrics to analyze
* @param current_window Current window size being tested
* @param accuracy_at_current Measured accuracy with current window
* @return Suggested next window size to try (1, 2, 4, or 8)
*/
uint32_t transition_metrics_binary_chop_suggest_window(const WordTransitionMetrics *metrics,
uint32_t current_window,
double accuracy_at_current);
#endif /* PHYSICS_PIPELINING_METRICS_H */