| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| #ifndef LAL_PONDER_H |
| #define LAL_PONDER_H |
|
|
| #include <math.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
|
|
| #define LAL_PONDER_MAX_STEPS 40 |
| #define LAL_PONDER_MAX_REC 8 |
| #define LAL_PONDER_EPS 1e-6f |
| #define LAL_PONDER_LOG_EPS 1e-12f |
|
|
| |
| |
| |
| typedef struct { |
| int enable; |
| int layer_halt; |
| int rec_iters; |
| float lambda; |
| float beta; |
| float gamma; |
| float lr_scale; |
| float threshold; |
| int infer_min_layer; |
| } PonderConfig; |
|
|
| extern PonderConfig g_ponder_cfg; |
|
|
| |
| extern float g_ponder_last_al; |
| extern float g_ponder_last_p; |
| extern float g_ponder_last_mean; |
|
|
| |
| |
| |
| typedef struct { |
| int in_dim; |
| float *w; |
| float b; |
| float *grad_w; |
| float grad_b; |
| float *m_w, *v_w; |
| float m_b, v_b; |
| } PonderLayer; |
|
|
| void ponder_layer_alloc(PonderLayer *u, int in_dim); |
| void ponder_layer_init(PonderLayer *u); |
| void ponder_layer_free(PonderLayer *u); |
|
|
| |
| |
| |
| typedef struct { |
| int n_steps; |
| int n_param; |
| float p[LAL_PONDER_MAX_STEPS]; |
| float c[LAL_PONDER_MAX_STEPS]; |
| float Rm[LAL_PONDER_MAX_STEPS]; |
| float prior[LAL_PONDER_MAX_STEPS]; |
| float gdot[LAL_PONDER_MAX_STEPS]; |
| float loss_al; |
| float loss_p; |
| float mean_step; |
| int active; |
| } PonderBuf; |
|
|
| |
| void ponder_dist_fill(PonderBuf *pb, const float *halts, int n_param); |
|
|
| |
| float ponder_halt(const PonderLayer *u, const float *x, int n); |
|
|
| |
| void ponder_grad(PonderBuf *pb, float *dpre); |
|
|
| |
| |
| |
| typedef struct { |
| long n_tokens; |
| double depth_sum; |
| int early_exits; |
| int last_depth; |
| float last_c[LAL_PONDER_MAX_STEPS]; |
| int last_n_steps; |
| } PonderStats; |
| extern PonderStats g_ponder_stats; |
|
|
| void ponder_stats_reset(void); |
| void ponder_stats_record(const PonderBuf *pb, int early_exit); |
| void ponder_stats_print(const char *tag); |
|
|
| |
| |
| |
| void ponder_config_from_env(void); |
|
|
| #ifdef LAL_PONDER_IMPLEMENTATION |
|
|
| PonderConfig g_ponder_cfg = {0}; |
| float g_ponder_last_al = 0.0f; |
| float g_ponder_last_p = 0.0f; |
| float g_ponder_last_mean = 0.0f; |
| PonderStats g_ponder_stats = {0}; |
|
|
| static float ponder_sigmoidf(float z) { |
| if (z > 30.0f) z = 30.0f; |
| if (z < -30.0f) z = -30.0f; |
| return 1.0f / (1.0f + expf(-z)); |
| } |
|
|
| void ponder_layer_alloc(PonderLayer *u, int in_dim) { |
| memset(u, 0, sizeof(*u)); |
| u->in_dim = in_dim; |
| u->w = calloc(in_dim, sizeof(float)); |
| u->grad_w = calloc(in_dim, sizeof(float)); |
| u->m_w = calloc(in_dim, sizeof(float)); |
| u->v_w = calloc(in_dim, sizeof(float)); |
| u->b = 0.0f; u->grad_b = 0.0f; u->m_b = 0.0f; u->v_b = 0.0f; |
| } |
|
|
| void ponder_layer_init(PonderLayer *u) { |
| |
| |
| for (int i = 0; i < u->in_dim; i++) u->w[i] = 0.0f; |
| float lam = g_ponder_cfg.lambda; |
| if (lam < 0.01f) lam = 0.01f; |
| if (lam > 0.99f) lam = 0.99f; |
| u->b = logf(lam / (1.0f - lam)); |
| for (int i = 0; i < u->in_dim; i++) u->grad_w[i] = 0.0f; |
| u->grad_b = 0.0f; |
| for (int i = 0; i < u->in_dim; i++) { u->m_w[i] = 0.0f; u->v_w[i] = 0.0f; } |
| u->m_b = 0.0f; u->v_b = 0.0f; |
| } |
|
|
| void ponder_layer_free(PonderLayer *u) { |
| free(u->w); free(u->grad_w); free(u->m_w); free(u->v_w); |
| memset(u, 0, sizeof(*u)); |
| } |
|
|
| |
| float ponder_halt(const PonderLayer *u, const float *x, int n) { |
| float z = u->b; |
| for (int i = 0; i < n; i++) z += u->w[i] * x[i]; |
| float p = ponder_sigmoidf(z); |
| if (p < LAL_PONDER_EPS) p = LAL_PONDER_EPS; |
| if (p > 1.0f - LAL_PONDER_EPS) p = 1.0f - LAL_PONDER_EPS; |
| return p; |
| } |
|
|
| void ponder_dist_fill(PonderBuf *pb, const float *halts, int n_param) { |
| |
| int N = n_param + 1; |
| if (N > LAL_PONDER_MAX_STEPS) N = LAL_PONDER_MAX_STEPS; |
| n_param = N - 1; |
| pb->n_steps = N; |
| pb->n_param = n_param; |
| pb->active = 1; |
|
|
| float lam = g_ponder_cfg.lambda; |
| |
| { |
| float acc = 0.0f; |
| for (int l = 0; l < n_param; l++) { |
| pb->prior[l] = lam * powf(1.0f - lam, (float)l); |
| acc += pb->prior[l]; |
| } |
| pb->prior[n_param] = 1.0f - acc; |
| if (pb->prior[n_param] < LAL_PONDER_LOG_EPS) pb->prior[n_param] = LAL_PONDER_LOG_EPS; |
| } |
|
|
| |
| float Rm = 1.0f, Q = 0.0f; |
| pb->Rm[0] = 1.0f; |
| for (int l = 0; l < n_param; l++) { |
| float p = halts[l]; |
| if (p < LAL_PONDER_EPS) p = LAL_PONDER_EPS; |
| if (p > 1.0f - LAL_PONDER_EPS) p = 1.0f - LAL_PONDER_EPS; |
| pb->p[l] = p; |
| pb->c[l] = Rm * p; |
| Q += pb->c[l]; |
| Rm = 1.0f - Q; |
| if (Rm < 0.0f) Rm = 0.0f; |
| pb->Rm[l + 1] = Rm; |
| } |
| pb->p[n_param] = 1.0f; |
| pb->c[n_param] = Rm; |
| pb->Rm[N] = 0.0f; |
|
|
| |
| float al = 0.0f; |
| for (int l = 0; l < N; l++) { |
| float cl = pb->c[l]; |
| if (cl < LAL_PONDER_LOG_EPS) cl = LAL_PONDER_LOG_EPS; |
| al -= pb->prior[l] * logf(cl); |
| } |
| pb->loss_al = al; |
|
|
| |
| float lp = 0.0f; |
| for (int l = 1; l < N; l++) { |
| float r = pb->Rm[l]; |
| lp += r * r; |
| } |
| pb->loss_p = lp; |
|
|
| |
| float ms = 0.0f; |
| for (int l = 0; l < N; l++) ms += (float)l * pb->c[l]; |
| pb->mean_step = ms; |
| } |
|
|
| void ponder_grad(PonderBuf *pb, float *dpre) { |
| int n_param = pb->n_param; |
| int N = pb->n_steps; |
|
|
| |
| |
| |
| |
| |
| float tailG[LAL_PONDER_MAX_STEPS]; |
| float tailPrior[LAL_PONDER_MAX_STEPS]; |
| float tailSq[LAL_PONDER_MAX_STEPS]; |
| tailG[n_param] = 0.0f; tailPrior[n_param] = 0.0f; tailSq[n_param] = 0.0f; |
| |
| for (int j = n_param - 1; j >= 0; j--) { |
| tailG[j] = tailG[j + 1] + pb->c[j + 1] * pb->gdot[j + 1]; |
| tailPrior[j] = tailPrior[j + 1] + pb->prior[j + 1]; |
| tailSq[j] = tailSq[j + 1] + pb->Rm[j + 1] * pb->Rm[j + 1]; |
| } |
|
|
| for (int j = 0; j < n_param; j++) { |
| float p = pb->p[j]; |
| float one_minus_p = 1.0f - p; |
| if (one_minus_p < LAL_PONDER_EPS) one_minus_p = LAL_PONDER_EPS; |
|
|
| float dp_task = pb->Rm[j] * pb->gdot[j] - tailG[j] / one_minus_p; |
| float dp_al = -pb->prior[j] / p + tailPrior[j] / one_minus_p; |
| float dp_p = -2.0f * tailSq[j] / one_minus_p; |
|
|
| float dp = dp_task |
| + g_ponder_cfg.beta * dp_al |
| + g_ponder_cfg.gamma * dp_p; |
|
|
| |
| if (dp > 100.0f) dp = 100.0f; |
| if (dp < -100.0f) dp = -100.0f; |
|
|
| |
| dpre[j] = dp * p * one_minus_p; |
| } |
| } |
|
|
| |
| void ponder_stats_reset(void) { |
| g_ponder_stats.n_tokens = 0; |
| g_ponder_stats.depth_sum = 0.0; |
| g_ponder_stats.early_exits = 0; |
| g_ponder_stats.last_depth = 0; |
| g_ponder_stats.last_n_steps = 0; |
| } |
|
|
| void ponder_stats_record(const PonderBuf *pb, int early_exit) { |
| g_ponder_stats.n_tokens++; |
| g_ponder_stats.depth_sum += pb->mean_step; |
| if (early_exit) g_ponder_stats.early_exits++; |
| g_ponder_stats.last_depth = (int)(pb->mean_step + 0.5f); |
| g_ponder_stats.last_n_steps = pb->n_steps; |
| int n = pb->n_steps; |
| if (n > LAL_PONDER_MAX_STEPS) n = LAL_PONDER_MAX_STEPS; |
| for (int l = 0; l < n; l++) g_ponder_stats.last_c[l] = pb->c[l]; |
| } |
|
|
| void ponder_stats_print(const char *tag) { |
| if (!g_ponder_cfg.enable || g_ponder_stats.n_tokens == 0) return; |
| float avg = (float)(g_ponder_stats.depth_sum / (double)g_ponder_stats.n_tokens); |
| printf("[PONDER%s] tokens=%ld avg_depth=%.2f early_exit=%ld/%ld last_dist=[", |
| tag ? tag : "", g_ponder_stats.n_tokens, avg, |
| g_ponder_stats.early_exits, g_ponder_stats.n_tokens); |
| int n = g_ponder_stats.last_n_steps; |
| if (n > 8) n = 8; |
| for (int l = 0; l < n; l++) printf("%.3f%s", g_ponder_stats.last_c[l], l + 1 < n ? " " : ""); |
| if (g_ponder_stats.last_n_steps > 8) printf("..."); |
| printf("]\n"); |
| } |
|
|
| |
| static float ponder_env_float(const char *key, float dflt) { |
| const char *v = getenv(key); |
| if (!v || !v[0]) return dflt; |
| float x = (float)atof(v); |
| return x; |
| } |
| static int ponder_env_int(const char *key, int dflt) { |
| const char *v = getenv(key); |
| if (!v || !v[0]) return dflt; |
| return atoi(v); |
| } |
|
|
| void ponder_config_from_env(void) { |
| PonderConfig *c = &g_ponder_cfg; |
| c->enable = ponder_env_int("LAL_PONDER", 1); |
| c->layer_halt = ponder_env_int("LAL_PONDER_LAYER", 1); |
| c->rec_iters = ponder_env_int("LAL_PONDER_REC", 2); |
| if (c->rec_iters < 1) c->rec_iters = 1; |
| if (c->rec_iters > LAL_PONDER_MAX_REC) c->rec_iters = LAL_PONDER_MAX_REC; |
| c->lambda = ponder_env_float("LAL_PONDER_LAMBDA", 0.5f); |
| if (c->lambda < 0.01f) c->lambda = 0.01f; |
| if (c->lambda > 0.99f) c->lambda = 0.99f; |
| c->beta = ponder_env_float("LAL_PONDER_BETA", 0.01f); |
| c->gamma = ponder_env_float("LAL_PONDER_GAMMA", 0.01f); |
| c->lr_scale = ponder_env_float("LAL_PONDER_LR", 1.0f); |
| if (c->lr_scale < 0.0f) c->lr_scale = 0.0f; |
| c->threshold = ponder_env_float("LAL_PONDER_THRESHOLD", 0.99f); |
| if (c->threshold < 0.5f) c->threshold = 0.5f; |
| if (c->threshold > 1.0f) c->threshold = 1.0f; |
| c->infer_min_layer = ponder_env_int("LAL_PONDER_MIN_LAYER", 1); |
| if (c->infer_min_layer < 0) c->infer_min_layer = 0; |
|
|
| |
| if (c->enable && !c->layer_halt && c->rec_iters <= 1) { |
| c->enable = 0; |
| } |
|
|
| printf("[PONDER] enable=%d layer_halt=%d rec_iters=%d lambda=%.3f beta=%.4f gamma=%.4f " |
| "lr_scale=%.2f threshold=%.2f min_layer=%d\n", |
| c->enable, c->layer_halt, c->rec_iters, c->lambda, c->beta, c->gamma, |
| c->lr_scale, c->threshold, c->infer_min_layer); |
| if (!c->enable) { |
| printf("[PONDER] 已停用 — 前向/反向/推理与改造前完全一致 (baseline)\n"); |
| } else { |
| int nL_est = 0; |
| (void)nL_est; |
| printf("[PONDER] 模式: %s%s%s\n", |
| c->layer_halt ? "逐层停机" : "", |
| (c->layer_halt && c->rec_iters > 1) ? " + " : "", |
| c->rec_iters > 1 ? "块内循环(末块)" : "单遍读出"); |
| } |
| } |
|
|
| #endif |
| #endif |
|
|