diff --git a/src/components/AssumptionsTab.jsx b/src/components/AssumptionsTab.jsx index c91c344..c9fd7f8 100644 --- a/src/components/AssumptionsTab.jsx +++ b/src/components/AssumptionsTab.jsx @@ -1,6 +1,6 @@ import React, { useMemo, useState, useRef, useCallback, useEffect } from 'react'; import { ASSUMPTION_SEGMENTS, GLOBAL_PARAMS, TRANSLATION_INTENSITIES } from '../data/assumptions.js'; -import { formatNumber } from '../engine/calculations.js'; +import { formatNumber, softEfficiencyCap } from '../engine/calculations.js'; /* ── Brain equivalency constants ── */ const BRAIN = GLOBAL_PARAMS.brainEquivalency; @@ -73,7 +73,7 @@ const BRAIN_COLUMNS = [ { valueKey: 'cumulativeGain', label: 'Cumulative Eff. (x)', format: v => v < 1000 ? v.toFixed(1) + 'x' : (v / 1000).toFixed(1) + 'Kx' }, { valueKey: 'wattsPerBrainEquiv', label: 'W per Brain-Equiv', format: v => v >= 1000 ? (v / 1000).toFixed(1) + ' kW' : v.toFixed(0) + ' W' }, { valueKey: 'brainEfficiencyPct', label: '% of Brain Eff.', format: v => v < 1 ? v.toFixed(2) + '%' : v < 100 ? v.toFixed(1) + '%' : v.toFixed(0) + '%', help: `Human brain = ${GLOBAL_PARAMS.brainEquivalency.humanBrainWatts}W` }, - { valueKey: 'atAsymptote', label: 'Limit?', format: v => v ? 'AT LIMIT' : '\u2014' } + { valueKey: 'atAsymptote', label: 'Returns', format: v => v ? 'DIMINISHING' : 'linear' } ]; function AssumptionsTab({ assumptions, onAssumptionChange, onRunSimulation, isSimulating, results }) { @@ -377,14 +377,15 @@ function AssumptionsTab({ assumptions, onAssumptionChange, onRunSimulation, isSi const startingWatts = BRAIN.startingWattsPerBrainEquiv; const brainWatts = BRAIN.humanBrainWatts; - // Cap: AI can be at most 5× more efficient than the human brain (30W). - // At 5× efficiency → 6W per brain-equiv. maxCumulativeGain = 10000 / 6 ≈ 1667×. + // Knee: gains above this level see logarithmic diminishing returns. + // maxCumulativeGain = 10000 / 3 ≈ 3333×. Beyond the knee, improvements + // continue but much slower — reflecting practical engineering limits. const minWatts = BRAIN.minWattsPerBrainEquiv; const maxCumulativeGain = startingWatts / minWatts; - let cumulativeGain = 1.0; - let asymptoteReached = false; - let firstAsymptoteIdx = -1; + let rawCumulativeGain = 1.0; + let pastKnee = false; + let firstKneeIdx = -1; const results = {}; @@ -392,33 +393,32 @@ function AssumptionsTab({ assumptions, onAssumptionChange, onRunSimulation, isSi const years = BLOCK_YEARS[idx] || 1; const annualGain = efficiencySummary[block.key]?.totalGain || 1; - if (!asymptoteReached) { - // Compound the annual gain over the block's duration - const blockGain = Math.pow(annualGain, years); - cumulativeGain *= blockGain; + // Always compound — gains never stop, just slow down past the knee + const blockGain = Math.pow(annualGain, years); + rawCumulativeGain *= blockGain; - // Check if we hit the asymptote - if (cumulativeGain >= maxCumulativeGain) { - cumulativeGain = maxCumulativeGain; - asymptoteReached = true; - firstAsymptoteIdx = idx; - } + // Soft cap: below the knee linear, above logarithmic diminishing returns + const effectiveGain = softEfficiencyCap(rawCumulativeGain, maxCumulativeGain); + + if (!pastKnee && rawCumulativeGain >= maxCumulativeGain) { + pastKnee = true; + firstKneeIdx = idx; } - const wattsPerBrainEquiv = Math.max(startingWatts / cumulativeGain, minWatts); + const wattsPerBrainEquiv = Math.max(startingWatts / effectiveGain, minWatts); const brainEfficiencyPct = (brainWatts / wattsPerBrainEquiv) * 100; results[block.key] = { - cumulativeGain, + cumulativeGain: effectiveGain, wattsPerBrainEquiv, brainEfficiencyPct, - atAsymptote: asymptoteReached + atAsymptote: pastKnee }; }); return { perBlock: results, - firstAsymptoteIdx + firstAsymptoteIdx: firstKneeIdx }; }, [efficiencySummary, timeBlocks]); @@ -500,14 +500,13 @@ function AssumptionsTab({ assumptions, onAssumptionChange, onRunSimulation, isSi }); }, [impliedAIs, results]); - /* ── Check if a row is past the asymptote (for greying out efficiency cells) ── */ + /* ── Check if a row is past the efficiency knee (diminishing returns) ── */ const isRowPastAsymptote = useCallback((rowIdx) => { - const { firstAsymptoteIdx } = brainEquivalency; - if (firstAsymptoteIdx === -1) return false; - // Grey out the row that hit the asymptote and all rows after it - return rowIdx >= firstAsymptoteIdx; - }, [brainEquivalency]); + // With the soft cap, cells are never fully disabled — gains continue, + // just slower. Return false so all rows stay editable. + return false; + }, []); /* ── Render: table header row ── */ @@ -746,7 +745,7 @@ function AssumptionsTab({ assumptions, onAssumptionChange, onRunSimulation, isSi
W/Brain-Equiv
-
floor {BRAIN.minWattsPerBrainEquiv}W
+
knee {BRAIN.minWattsPerBrainEquiv}W
Brain Equivalents
@@ -771,11 +770,12 @@ function AssumptionsTab({ assumptions, onAssumptionChange, onRunSimulation, isSi {row.totalPowerGW.toFixed(1)} - + {row.wattsPerBrainEquiv >= 1000 ? (row.wattsPerBrainEquiv / 1000).toFixed(1) + ' kW' - : row.wattsPerBrainEquiv.toFixed(0) + ' W'} - {row.atEfficiencyLimit ? ' (LIMIT)' : ''} + : row.wattsPerBrainEquiv < 10 + ? row.wattsPerBrainEquiv.toFixed(1) + ' W' + : row.wattsPerBrainEquiv.toFixed(0) + ' W'} @@ -918,9 +918,9 @@ function AssumptionsTab({ assumptions, onAssumptionChange, onRunSimulation, isSi Compares AI compute efficiency to the human brain ({BRAIN.humanBrainWatts}W). Starting at {(BRAIN.startingWattsPerBrainEquiv / 1000).toFixed(0)}kW per brain-equivalent of cognitive work, efficiency improvements compound over time. - Asymptotes at {BRAIN.maxEfficiencyVsBrain}× brain efficiency - ({BRAIN.minWattsPerBrainEquiv}W per brain-equiv). Once the - asymptote is reached, further efficiency cells are locked. + Soft knee at {BRAIN.maxEfficiencyVsBrain}× brain efficiency + ({BRAIN.minWattsPerBrainEquiv}W per brain-equiv) — beyond this, + gains continue but with logarithmic diminishing returns.

{renderBrainEquivalencyTable()} diff --git a/src/data/assumptions.js b/src/data/assumptions.js index 9943926..6652a56 100644 --- a/src/data/assumptions.js +++ b/src/data/assumptions.js @@ -91,9 +91,9 @@ export const GLOBAL_PARAMS = { brainEquivalency: { humanBrainWatts: 30, // Human brain power consumption in watts startingWattsPerBrainEquiv: 10000, // Starting AI watts per brain-equivalent of cognitive work - maxEfficiencyVsBrain: 5, // Asymptote: AI can be at most 5x more efficient than the brain - // At 5x efficiency, AI does brain-equivalent work at 30W / 5 = 6W - minWattsPerBrainEquiv: 6 // = humanBrainWatts / maxEfficiencyVsBrain + maxEfficiencyVsBrain: 10, // Asymptote: AI can be at most 10x more efficient than the brain + // At 10x efficiency, AI does brain-equivalent work at 30W / 10 = 3W + minWattsPerBrainEquiv: 3 // = humanBrainWatts / maxEfficiencyVsBrain } }; diff --git a/src/engine/calculations.js b/src/engine/calculations.js index 4eb6eb0..b62cf0e 100644 --- a/src/engine/calculations.js +++ b/src/engine/calculations.js @@ -150,13 +150,25 @@ function getNodeType(nodeId) { const EPSILON = 1e-10; -// Thermodynamic efficiency ceiling: shared across simulation engine and brain equivalency. -// No matter how clever the algorithm or optimized the silicon, inference cannot go below -// ~6W per operation (5× more efficient than the human brain at ~30W). Current GPU-class -// accelerators draw ~700W, so max compound efficiency gain is bounded by 700W / 6W ≈ 117×. +// Efficiency ceiling (soft knee): gains below the knee are linear; above, logarithmic +// diminishing returns. The knee is set by the ratio of current GPU power to a practical +// floor (~3W = 10× more efficient than the human brain at 30W). Beyond the knee, +// improvements continue but at a dramatically slower pace — reflecting engineering +// diminishing returns rather than a hard thermodynamic wall. export const CURRENT_GPU_WATTS = 700; -export const THERMODYNAMIC_FLOOR_WATTS = 6; -export const MAX_EFFICIENCY_GAIN = CURRENT_GPU_WATTS / THERMODYNAMIC_FLOOR_WATTS; +export const THERMODYNAMIC_FLOOR_WATTS = 3; +export const MAX_EFFICIENCY_GAIN = CURRENT_GPU_WATTS / THERMODYNAMIC_FLOOR_WATTS; // ~233× + +/** + * Soft asymptotic efficiency cap with diminishing returns above the knee. + * Below the knee: gain = raw (linear, unchanged). + * Above the knee: gain = knee × (1 + ln(raw / knee)) — logarithmic. + * Continuous at the knee. Always increasing, but dramatically slower above it. + */ +export function softEfficiencyCap(raw, knee) { + if (raw <= knee) return raw; + return knee * (1 + Math.log(raw / knee)); +} // Planning knobs const CATCHUP_MONTHS = 6; @@ -501,12 +513,11 @@ function computeRequiredGpus(month, trajectories, demandAssumptions, efficiencyA // Efficiency gain: M decays (models get cheaper → more tok/s), S and H grow throughput. // H_memory: inference is memory-bandwidth-bound (not compute-bound), so HBM generational // improvements (H_memory) directly increase inference tok/s alongside general H gains. - // Thermodynamic floor: no matter how clever the algorithm or how optimized the silicon, - // inference cannot go below ~6W per operation (5× more efficient than the human brain - // at ~30W). Current GPU-class accelerators draw ~700W, so the maximum compound - // efficiency gain across all axes is bounded by 700W / 6W ≈ 117×. + // Soft efficiency ceiling: below ~233× (700W / 3W), gains are linear. Above the knee, + // diminishing returns kick in — improvements continue but at logarithmic pace, + // reflecting practical engineering limits rather than a hard thermodynamic wall. const rawEfficiencyGain = (1 / Math.max(eff.M_inference, EPSILON)) * eff.S_inference * eff.H * eff.H_memory; - const efficiencyGain = Math.min(rawEfficiencyGain, MAX_EFFICIENCY_GAIN); + const efficiencyGain = softEfficiencyCap(rawEfficiencyGain, MAX_EFFICIENCY_GAIN); // Per-segment GPU demand (with demandScale applied to token volumes) const consumerTokens = (inferenceDemand.consumer || 0) * demandScale; @@ -533,11 +544,11 @@ function computeRequiredGpus(month, trajectories, demandAssumptions, efficiencyA const totalTrainingHours = (frontierRuns * hoursFrontier) + (midtierRuns * hoursMidtier); const denomTraining = hoursPerMonth * utilTrn * eff.S_training * eff.H; - // Cap training efficiency the same way: M_training decays (numerator) while S*H grows - // (denominator), so the effective reduction factor = M / (S*H). Floor it at 1/MAX. - const rawTrainingFactor = eff.M_training / Math.max(denomTraining, EPSILON); - const minTrainingFactor = 1 / (hoursPerMonth * utilTrn * MAX_EFFICIENCY_GAIN); - const requiredTraining = totalTrainingHours * Math.max(rawTrainingFactor, minTrainingFactor); + // Soft cap training efficiency: compute raw gain = (S*H) / M, apply soft knee, + // then convert back to a cost factor. Gains continue past the knee but slow dramatically. + const rawTrainingGain = eff.S_training * eff.H / Math.max(eff.M_training, EPSILON); + const cappedTrainingGain = softEfficiencyCap(rawTrainingGain, MAX_EFFICIENCY_GAIN); + const requiredTraining = totalTrainingHours / (hoursPerMonth * utilTrn * cappedTrainingGain); return { requiredTotal: requiredInference + requiredTraining,