scripts: csv.py: Added saturate function

This is useful for enforcing an upper-bound on fracs based on their
total component.

Technically possible via decomposing + min + recomposing, but... Well
which one do you think is easier?

- saturate(x)
- frac(min(max(int(x), 0), total(x)), total(x))

And this assumes x is easily available and not some other expr (though
chaining csv.py could work around that).

---

The motivation for this was `make bench-widths`, where one read
benchmark could ruin the entire column due to introducing infinities.
Now:

  make bench # (squished a bit)
  probe           readed               progged                  erased
  b_wt_seq+w     1.0/1.0 (100.0%)   31.7/256.0 (12.4%)   4096.0/4096.0 (100.0%)
  b_wt_random+w  1.0/1.0 (100.0%)   15.3/256.0 (6.0%)    4096.0/4096.0 (100.0%)
  b_wt_logging+w 1.0/1.0 (100.0%)   15.4/256.0 (6.0%)    4096.0/4096.0 (100.0%)
  b_wt_many+w    1.0/1.0 (100.0%)   16.1/256.0 (6.3%)    4096.0/4096.0 (100.0%)
  b_rt_seq+r     1.0/1.0 (100.0%)  256.0/256.0 (100.0%)  4096.0/4096.0 (100.0%)
  b_rt_random+r  1.0/1.0 (100.0%)  256.0/256.0 (100.0%)  4096.0/4096.0 (100.0%)
  b_rt_many+r    1.0/1.0 (100.0%)  256.0/256.0 (100.0%)  4096.0/4096.0 (100.0%)
  TOTAL          1.0/1.0 (100.0%)  149.0/256.0 (58.2%)   4096.0/4096.0 (100.0%)
  #                                  ^- notably not infinity
This commit is contained in:
Christopher Haster
2026-02-06 17:05:30 -06:00
parent 440d303a6b
commit ad9b39a762
2 changed files with 18 additions and 6 deletions
+6 -6
View File
@@ -693,24 +693,24 @@ bench-widths: $(BENCH_CSV)
write,stat,read \
-bprobe='%(case)s+%(probe)s' \
-Fi='min(enumerate())' \
-freaded="avg(ffrac( \
-freaded="avg(saturate(ffrac( \
float(bench_readed)/float(bench_reads), \
max(1, $$( \
./scripts/bench.py -R$(BENCH_RUNNER) $(BENCHFLAGS) \
--list-implicit-defines \
| sed -n 's/^READ_WIDTH=\(.*\)/\1/p'))))" \
-fprogged="avg(ffrac( \
| sed -n 's/^READ_WIDTH=\(.*\)/\1/p')))))" \
-fprogged="avg(saturate(ffrac( \
float(bench_progged)/float(bench_progs), \
max(1, $$( \
./scripts/bench.py -R$(BENCH_RUNNER) $(BENCHFLAGS) \
--list-implicit-defines \
| sed -n 's/^PROG_WIDTH=\(.*\)/\1/p'))))" \
-ferased="avg(ffrac( \
| sed -n 's/^PROG_WIDTH=\(.*\)/\1/p')))))" \
-ferased="avg(saturate(ffrac( \
float(bench_erased)/float(bench_erases), \
max(1, $$( \
./scripts/bench.py -R$(BENCH_RUNNER) $(BENCHFLAGS) \
--list-implicit-defines \
| sed -n 's/^ERASE_WIDTH=\(.*\)/\1/p'))))" \
| sed -n 's/^ERASE_WIDTH=\(.*\)/\1/p')))))" \
$(SUMMARYFLAGS))
## Show heap/stack/disk usage
+12
View File
@@ -1099,6 +1099,18 @@ class CsvExpr:
else:
return v.b
@func('saturate', 'a')
class Saturate(Expr):
"""Limit to total part of a fraction"""
def eval(self, fields={}, state=None):
v = self.a.eval(fields, state)
if not hasattr(v, '__frac__'):
return v
elif isinstance(v, CsvFrac):
return CsvFrac(min(max(v.a, CsvInt(0)), v.b), v.b)
elif isinstance(v, CsvFfrac):
return CsvFfrac(min(max(v.a, CsvFloat(0)), v.b), v.b)
@func('abs', 'a')
class Abs(Expr):
"""Absolute value"""