Initial text cleanup
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env julia
|
||||
#
|
||||
# bench_model.jl — microbenchmark the classifier in isolation, with no server,
|
||||
# bench_model.jl: microbenchmark the classifier in isolation, with no server,
|
||||
# no queue, and no disk in the way.
|
||||
#
|
||||
# bin/bench.jl measures the *pipeline*: it reports stage 1 as one number, the
|
||||
@@ -12,7 +12,7 @@
|
||||
#
|
||||
# read_features open, read 16 bytes, seek, read 16 bytes, scale
|
||||
# Lux.apply the network itself, on a feature vector already in memory
|
||||
# classify both together — what stage 1 actually calls per file
|
||||
# classify both together: what stage 1 actually calls per file
|
||||
#
|
||||
# Three properties are worth checking beyond the raw per-file cost:
|
||||
#
|
||||
@@ -21,7 +21,7 @@
|
||||
# (This is the same claim bin/bench.jl makes about memory, on the CPU axis.)
|
||||
# * Batching should be much cheaper per file. A 32x1 matmul wastes most of a
|
||||
# BLAS call; if batch-64 inference is many times cheaper per file, that is
|
||||
# the headroom a batching stage-1 would buy — worth knowing before building
|
||||
# the headroom a batching stage-1 would buy, worth knowing before building
|
||||
# one, since today the pipeline classifies strictly one file at a time.
|
||||
# * Inference should scale across threads. `Classifier` is shared read-only by
|
||||
# the whole stage-1 pool on the claim that Lux inference is pure. If per-file
|
||||
@@ -48,7 +48,7 @@ using Statistics
|
||||
using Printf
|
||||
|
||||
# The script is run directly, not as part of the package, so pull in exactly the
|
||||
# pieces the classifier needs. `Lux`/`JLD2` first — model.jl and classify.jl both
|
||||
# pieces the classifier needs. `Lux`/`JLD2` first, because model.jl and classify.jl both
|
||||
# assume the including scope already has them (see the note at the top of model.jl).
|
||||
using Lux
|
||||
using JLD2
|
||||
@@ -156,7 +156,7 @@ fmt2(x::Real) = @sprintf("%.2f", x)
|
||||
"""
|
||||
control_kernel(x) -> Float64
|
||||
|
||||
Pure arithmetic, no allocation, no library call — deliberately dependent
|
||||
Pure arithmetic, no allocation, no library call, and deliberately dependent
|
||||
(each step needs the last) so the compiler can't vectorize it away, and sized to
|
||||
land in the same microsecond neighbourhood as one `Lux.apply`.
|
||||
"""
|
||||
@@ -209,7 +209,7 @@ end
|
||||
"""
|
||||
Write a file of exactly `size` random bytes, in bounded chunks.
|
||||
|
||||
Content is random rather than zeros so the classifier sees a realistic input —
|
||||
Content is random rather than zeros so the classifier sees a realistic input,
|
||||
and so the filesystem can't cheat with a sparse file, which would make the tail
|
||||
`seek` unrepresentatively fast.
|
||||
"""
|
||||
@@ -252,7 +252,7 @@ function main(argv)
|
||||
Lux.apply(clf.model, x1, clf.ps, clf.st)
|
||||
end
|
||||
println()
|
||||
println("INFERENCE (Lux.apply, batch 1 — features already in memory)")
|
||||
println("INFERENCE (Lux.apply, batch 1; features already in memory)")
|
||||
println(" per call $(human_time(infer_ns)) $(human_rate(rate(infer_ns)))")
|
||||
println(" allocations $(human_bytes(infer_bytes)) per call")
|
||||
results["inference_batch1"] = (; ns = infer_ns, bytes = infer_bytes, per_sec = rate(infer_ns))
|
||||
@@ -302,14 +302,14 @@ function main(argv)
|
||||
results["read_features"] = read_rows
|
||||
flat = length(read_rows) > 1 ?
|
||||
maximum(r.ns for r in read_rows) / minimum(r.ns for r in read_rows) : 1.0
|
||||
@printf(" spread across a %.0fx size range: %.1fx — %s\n",
|
||||
@printf(" spread across a %.0fx size range: %.1fx, %s\n",
|
||||
maximum(sizes) / minimum(sizes), flat,
|
||||
flat < 3 ? "flat, as designed (it seeks to the tail)" :
|
||||
"NOT flat: something is reading more than 32 bytes")
|
||||
|
||||
# --- 4. classify(): what stage 1 calls, I/O and inference together.
|
||||
println()
|
||||
println("CLASSIFY (read_features + Lux.apply — one whole stage-1 file)")
|
||||
println("CLASSIFY (read_features + Lux.apply; one whole stage-1 file)")
|
||||
dir2 = mktempdir(; prefix = "fsmodel-")
|
||||
classify_ns = 0.0
|
||||
try
|
||||
@@ -378,7 +378,7 @@ function main(argv)
|
||||
end
|
||||
results["thread_scaling"] = thread_rows
|
||||
|
||||
# A poor scaling curve has two possible authors — the model or the box —
|
||||
# A poor scaling curve has two possible authors, the model or the box,
|
||||
# and the table alone can't tell them apart. So run the same sweep on a
|
||||
# kernel that is pure arithmetic with no allocation and no library
|
||||
# underneath: whatever *it* achieves is this machine's ceiling for
|
||||
|
||||
Reference in New Issue
Block a user