|
| 1 | +#lang racket |
| 2 | + |
| 3 | +(require "../ops/all.rkt" |
| 4 | + "machine.rkt" |
| 5 | + "run.rkt" |
| 6 | + "main.rkt") |
| 7 | + |
| 8 | +(provide rival-machine-test-precision |
| 9 | + rival-machine-search-precision |
| 10 | + rival-machine-find-optimal-precisions) |
| 11 | + |
| 12 | +; Test if a machine succeeds at a given point with a specific precision vector |
| 13 | +; Returns #t if the evaluation succeeds (good? and done?), #f otherwise |
| 14 | +(define (rival-machine-test-precision machine pt prec-vec) |
| 15 | + ; Load point into registers |
| 16 | + (define ival-pt |
| 17 | + (for/vector #:length (vector-length pt) |
| 18 | + ([x (in-vector pt)]) |
| 19 | + (ival x))) |
| 20 | + (rival-machine-load machine ival-pt) |
| 21 | + |
| 22 | + ; Set custom precision vector |
| 23 | + (set-rival-machine-iteration! machine 1) ; Don't use initial precision vector |
| 24 | + (vector-copy! (rival-machine-precisions machine) 0 prec-vec) |
| 25 | + (vector-copy! (rival-machine-repeats machine) 0 (rival-machine-initial-repeats machine)) |
| 26 | + (rival-machine-run machine (rival-machine-default-hint machine)) |
| 27 | + |
| 28 | + ; Check result |
| 29 | + (define-values (good? done? bad? stuck? fvec) (rival-machine-return machine)) |
| 30 | + (and good? done?)) |
| 31 | + |
| 32 | +; Binary search for the lowest precision at index idx that makes the machine succeed |
| 33 | +; Returns the minimum precision in [min-prec, max-prec] where evaluation succeeds, |
| 34 | +; or #f if even max-prec fails |
| 35 | +(define (rival-machine-search-precision machine pt prec-vec idx) |
| 36 | + (define test-vec (vector-copy prec-vec)) |
| 37 | + (define max-prec (vector-ref test-vec idx)) |
| 38 | + |
| 39 | + ; Check if max-prec works at all |
| 40 | + (unless (rival-machine-test-precision machine pt test-vec) |
| 41 | + (error 'rival-machine-search-precision "max-prec does not succeed")) |
| 42 | + |
| 43 | + ; Binary search for minimum |
| 44 | + (let loop ([lo 2] |
| 45 | + [hi max-prec]) |
| 46 | + (if (>= lo hi) |
| 47 | + hi |
| 48 | + (let* ([mid (quotient (+ lo hi) 2)]) |
| 49 | + (vector-set! test-vec idx mid) |
| 50 | + (if (rival-machine-test-precision machine pt test-vec) |
| 51 | + (loop lo mid) |
| 52 | + (loop (+ mid 1) hi)))))) |
| 53 | + |
| 54 | +; Run thunk n times and return the minimum time |
| 55 | +(define (time-min thunk #:min [n 5] #:sum [m 10]) |
| 56 | + (thunk) ; Discard warm-up run |
| 57 | + (apply min |
| 58 | + (for/list ([i (in-range n)]) |
| 59 | + (define start (current-inexact-milliseconds)) |
| 60 | + (for ([i (in-range m)]) |
| 61 | + (thunk)) |
| 62 | + (/ (- (current-inexact-milliseconds) start) m)))) |
| 63 | + |
| 64 | +; Find optimal precisions for a machine at a given point |
| 65 | +(define (rival-machine-find-optimal-precisions machine pt) |
| 66 | + ; Extract the precision assignment, assuming no slack |
| 67 | + (define out (rival-apply machine pt)) |
| 68 | + (set-rival-machine-iteration! machine 1) ; Don't use initial precision vector |
| 69 | + (rival-machine-adjust machine (rival-machine-default-hint machine)) |
| 70 | + (define max-precs (vector-copy (rival-machine-precisions machine))) |
| 71 | + |
| 72 | + (cond |
| 73 | + [(rival-machine-test-precision machine pt max-precs) |
| 74 | + ; Timed run with rival-apply (full evaluation), take min of 5 runs |
| 75 | + (define final-time (time-min (lambda () (rival-machine-test-precision machine pt max-precs)))) |
| 76 | + |
| 77 | + ; Start with max precisions |
| 78 | + (define optimal-precs (vector-copy max-precs)) |
| 79 | + (define n-instrs (vector-length (rival-machine-instructions machine))) |
| 80 | + (for ([idx (in-range (- n-instrs 1) -1 -1)]) |
| 81 | + (vector-set! optimal-precs idx (rival-machine-search-precision machine pt optimal-precs idx))) |
| 82 | + |
| 83 | + ; Time run with optimal precisions |
| 84 | + (define optimal-time (time-min (lambda () (rival-machine-test-precision machine pt optimal-precs)))) |
| 85 | + |
| 86 | + ; Return both ratios and precision vectors |
| 87 | + (list optimal-precs optimal-time max-precs final-time)] |
| 88 | + [else |
| 89 | + #f])) |
0 commit comments