Code Patterns
Quick reference for flopscope operations, including operators, FLOP costs, and common patterns for mean and variance propagation.
Quick reference for flopscope operations. All examples assume import flopscope as flops and import flopscope.numpy as fnp.
Operators are tracked
Python arithmetic operators (+, -, *, /, @) on fnp.ndarray values are
FLOP-tracked — you do not need to use the verbose fnp.add, fnp.multiply, etc. forms.
import flopscope as flops
import flopscope.numpy as fnp
a = fnp.ones(4)
b = fnp.ones(4)
# These are all equivalent and all tracked:
c = a + b # tracked: same as fnp.add(a, b)
d = a * b # tracked: same as fnp.multiply(a, b)
e = a / b # tracked: same as fnp.divide(a, b)
W = fnp.eye(4)
v = fnp.ones(4)
f = W @ v # tracked: same as fnp.matmul(W, v)
g = W.T @ v # tracked: transpose is free, matmul is tracked
h = W.T @ W @ v # tracked: two matmuls, chained with @Use operators whenever they improve readability. The verbose fnp.* forms are still
available but are no longer required for tracking purposes.
Operation costs
flopscope 0.9.1 prices each op as flop_cost x weight x dtype_rate. The weight
falls into four tiers, and dtype_rate multiplies the bill by ~2x for float64 (and
more for complex):
- Free (0) — views only: basic indexing/slices,
transpose,diagextraction,real/imag. - 1x per element — arithmetic and data movement: element-wise ops,
sqrt/abs,copy,reshape/ravel,stack/concatenate/tile/repeat, fills (ones/full/eye), scatters (fill_diagonal,put). - 4x per element — value lookup / reordering: fancy and boolean indexing,
take,sort/argsort, set-ops, histograms, random reordering, and 3-argwhere. - 16x per element — transcendentals:
exp,log,sin/cos,tanh,**. matmulisO(m x n x k)and dominates budgets.
Figures below are float32 baselines — a guide, not a guarantee. The ground truth is
budget.summary(), and the authoritative per-op model is the flopscope cost reference.
| What you want | Code | FLOP cost (float32) | Notes |
|---|---|---|---|
| Create zeros | fnp.zeros((n, n)) | 0 | Free (also empty) |
| Create ones / full / eye | fnp.ones(n) | n | Fills are charged (only zeros is free) |
| Wrap existing data | fnp.array(data) | n | Materializes a copy; numeric dtypes only (see below) |
| Matrix multiply | fnp.matmul(A, B) | O(m x n x k) | Dominates budgets |
| Element-wise add | fnp.add(a, b) | 1 per element | Also sub, mul, div |
| ReLU | fnp.maximum(x, 0.0) | 1 per element | |
| Square root / abs | fnp.sqrt(x), fnp.abs(x) | 1 per element | |
| Exponential | fnp.exp(x) | 16 per element | Transcendental |
| Logarithm | fnp.log(x) | 16 per element | Transcendental |
| Power / trig | x ** 2, fnp.sin(x) | 16 per element | Transcendental; use x * x for squares |
| Transpose | fnp.transpose(W) | 0 | Free (view) |
| Reshape / ravel | fnp.reshape(x, shape) | n | Materializes |
| Extract diagonal | fnp.diag(M) | 0 | Free |
| Set diagonal | fnp.fill_diagonal(M, v) | n | Scatter write |
| Outer product | fnp.outer(a, b) | n x m | |
| Sum / mean / max | fnp.sum(x, axis=0) | input size | |
| Stack / concatenate | fnp.stack(rows, axis=0) | total size | Materializes |
| Basic index / slice | x[0], x[:, 3] | 0 | Free (view) |
| Fancy / boolean index | x[idx], x[mask] | 4 per element | Gather (mask: numel + 4 x selected) |
Select with where | fnp.where(c, a, b) | 4 per element | Was free before 0.9.0 |
| Sort / gather | fnp.sort(x), fnp.take(x, i) | 4 per element | Order / selector-deriving |
| Open-mesh index grid | fnp.ix_(i, j) | total output size | Was free before 0.11.0; each Boolean argument adds numel(arg) for the internal nonzero scan; rejects ndarray subclasses such as MaskedArray / memmap |
Numeric dtypes only.
fnp.array(data)requires data that coerces to a numeric dtype — bool, integer, unsigned integer, float or complex. Mixed, string, bytes,datetime64,timedelta64and object input now raiseflopscope.errors.UnsupportedDtypeError. Do not plan on converting with plainnumpyfirst — the grader sandbox does not provide it. Build numeric arrays from already-numeric scalars with an explicitdtype=fnp.float64, and hold ragged or mixed data in a Python list of numeric arrays rather than one object array.
Common patterns
Standard normal PDF and CDF (built-in)
flopscope provides built-in PDF and CDF functions that are FLOP-tracked:
import flopscope as flops
import flopscope.numpy as fnp
phi = flops.stats.norm.pdf(x) # standard normal PDF
Phi = flops.stats.norm.cdf(x) # standard normal CDFThese are the recommended approach — all example estimators use them. The manual implementations below are shown for reference.
Standard normal PDF (for ReLU expectation)
import flopscope as flops
import flopscope.numpy as fnp
def norm_pdf(x):
"""phi(x) = exp(-x^2/2) / sqrt(2*pi)"""
return fnp.exp(-0.5 * x * x) / fnp.sqrt(2.0 * fnp.pi)Standard normal CDF
Pure flopscope implementation using the Abramowitz & Stegun approximation (accurate to <7.5e-8):
import flopscope as flops
import flopscope.numpy as fnp
_P = 0.2316419
_A1, _A2, _A3 = 0.319381530, -0.356563782, 1.781477937
_A4, _A5 = -1.821255978, 1.330274429
def norm_cdf(x):
t = 1.0 / (1.0 + _P * fnp.abs(x))
poly = ((((_A5 * t + _A4) * t + _A3) * t + _A2) * t + _A1) * t
pdf = fnp.exp(-0.5 * x * x) / fnp.sqrt(2.0 * fnp.pi)
cdf = 1.0 - pdf * poly
return fnp.where(x >= 0, cdf, 1.0 - cdf)Use the pure-flopscope version above. The grader sandbox does not provide
scipy(or any third-party PyPI package) — onlyflopscope, thewhestbenchAPI, and the Python standard library are importable — and only flopscope operations are FLOP-counted. In Phase 2 there is norequirements.txtescape hatch: bundling scipy, numpy, a BLAS, or any compiled kernel is prohibited, not merely uncounted.
ReLU expectation (E[max(0, z)] where z ~ N(mu, sigma^2))
import flopscope as flops
import flopscope.numpy as fnp
alpha = mu_pre / sigma_pre
E_relu = mu_pre * norm_cdf(alpha) + sigma_pre * norm_pdf(alpha)See 02_mean_propagation.py (in the starter kit) for a complete worked example using these patterns.
Per-neuron variance propagation (diagonal)
import flopscope as flops
import flopscope.numpy as fnp
# var_pre[i] = sum_j W[j,i]^2 * var[j]
var_pre = (w * w).T @ varNext step
- Estimator Contract
- Manage Your FLOP Budget (in the starter kit)
- Algorithm Ideas (in the starter kit)