|
| 1 | +;;;; quilc-mon-prof.lisp |
| 2 | +;;;; |
| 3 | +;;;; Author: Mark David |
| 4 | + |
| 5 | +(in-package #:cl-quil-benchmarking) |
| 6 | + |
| 7 | + |
| 8 | + |
| 9 | +;;;; Monitoring and Profiling |
| 10 | + |
| 11 | +;; This builds on quilc-perf.lisp and is for monitoring and profiling, |
| 12 | +;; as opposed to simple benchmarks, and is a WIP in that we have not |
| 13 | +;; established a makefile entry to run this. That is because, while |
| 14 | +;; it's been useful to run for probing and experimenting in a REPL, we |
| 15 | +;; so far lack really good theory of operation and associated modes of |
| 16 | +;; running. We hope with time to get there. |
| 17 | + |
| 18 | + |
| 19 | +(defparameter *monitor-types* |
| 20 | + '(:mon #+sbcl :sb-sprof)) |
| 21 | + |
| 22 | +(defun monitor-run (program-type chip-type nq repeats monitor |
| 23 | + &optional report-type sample-interval) |
| 24 | + "Do REPEATS perf runs for PROGRAM-TYPE and CHIP-TYPE (as documented |
| 25 | + at the top of QUILC-PERF module) using the specified MONITOR, which |
| 26 | + must be one of those in the list *monitor-types*. Optional args |
| 27 | + REPORT-TYPE and SAMPLE-INTERVAL are only relevant when MONITOR is |
| 28 | + :SB-SPROF in which case REPORT-TYPE is passed as the same-named arg |
| 29 | + to SB-SPROF:REPORT, and SAMPLE-INTERVAL is passed as the same-named |
| 30 | + arg to SB-SPROF:START-PROFILING. Note as well that for :SB-SPROF |
| 31 | + monitor, only the current thread is profiled. This returns no |
| 32 | + useful value. It's just run in order to get output from the |
| 33 | + monitor." |
| 34 | + (when (not (member monitor *monitor-types*)) |
| 35 | + (unless (null monitor) ; if so, just silently default with no warning |
| 36 | + (warn "unrecognized monitor, should be one of ~s; using ~s" |
| 37 | + *monitor-types* (first *monitor-types*))) |
| 38 | + (setq monitor (first *monitor-types*))) |
| 39 | + (let (program chip) |
| 40 | + (format t "~2%****~%Building ~a program (nQ = ~d)... " program-type nq) |
| 41 | + (setq program (get-or-build-benchmark-program nq program-type)) |
| 42 | + (format t "DONE (~a).~%" program) |
| 43 | + (format t "Building ~a chip (nQ = ~d)... " chip-type nq) |
| 44 | + (setq chip (get-or-build-benchmark-chip nq chip-type)) |
| 45 | + (format t "DONE (~a).~%" chip) |
| 46 | + (format t "** Doing ~d run~p... **~%" repeats repeats) |
| 47 | + (let* ((*package* (find-package :cl-quil)) |
| 48 | + (thunk |
| 49 | + #'(lambda () |
| 50 | + (dotimes (i repeats) |
| 51 | + (prepare-environment-for-perf-run) |
| 52 | + (format t "#~d: Compiling program/chip ... " i) |
| 53 | + (let* ((t1 (get-internal-run-time)) |
| 54 | + (t2 (progn (do-one-quilc-perf-run program chip) |
| 55 | + (get-internal-run-time))) |
| 56 | + (elapsed-time (- t2 t1))) |
| 57 | + (format |
| 58 | + t |
| 59 | + "DONE (~,2f sec compiler, ~2df sec real time w/overhead).~%" |
| 60 | + ;; -- 2nd timing is real time, as opposed to |
| 61 | + ;; internal run time. 'Overhead' is primarily GC + |
| 62 | + ;; warming. |
| 63 | + (internal-time-to-seconds elapsed-time) |
| 64 | + (internal-time-to-seconds (- t2 t1)))))))) |
| 65 | + (ecase monitor |
| 66 | + (:mon (mon:monitor-form (funcall thunk))) |
| 67 | + #+sbcl |
| 68 | + (:sb-sprof |
| 69 | + (progn |
| 70 | + (sb-sprof:reset) |
| 71 | + (sb-sprof:start-profiling |
| 72 | + :sample-interval (or sample-interval 0.005) ; default = 0.01 |
| 73 | + :threads (list sb-thread:*current-thread*)) |
| 74 | + (funcall thunk) |
| 75 | + (sb-sprof:report |
| 76 | + :min-percent 3 |
| 77 | + :type (ecase report-type |
| 78 | + ((nil :flat) :flat) |
| 79 | + (:graph :graph))))))) |
| 80 | + (format t "** DONE with ~d runs. **~%" repeats))) |
| 81 | + |
| 82 | +(defun do-monitor-runs (&key start step end |
| 83 | + repeats monitor |
| 84 | + report-type sam sample-interval) |
| 85 | + (or repeats (setq repeats 3)) |
| 86 | + (loop :for nq := (or start 10) |
| 87 | + :then (+ nq (or step 10)) |
| 88 | + :when (> nq (or end start)) |
| 89 | + :do (return) |
| 90 | + :do (format t "~%**** NQ: ~d ****~%" nq) |
| 91 | + (loop :for program-type :in *benchmark-program-types* |
| 92 | + :do (loop :for chip-type :in *benchmark-chip-connectedness-types* |
| 93 | + :do (monitor-run |
| 94 | + program-type chip-type nq repeats monitor |
| 95 | + report-type sample-interval))))) |
| 96 | + |
| 97 | +;; Try this on SBCL: (do-monitor-runs :monitor ':sb-sprof) |
| 98 | + |
| 99 | + |
| 100 | + |
| 101 | + |
| 102 | +(defun do-one (nq) |
| 103 | + (do-one-nq-program-chip nq :hadamard :fully-connected)) |
| 104 | + |
| 105 | +(defparameter *min-sb-sprof-perf-pct* 1) |
| 106 | + |
| 107 | +(defun do-one-nq-program-chip (nq program-type chip-type) |
| 108 | + (let ((program (build-benchmark-program nq :hadamard)) |
| 109 | + (chip (build-benchmark-chip nq :fully-connected))) |
| 110 | + (sb-sprof:reset) |
| 111 | + (tg:gc :full t) |
| 112 | + (sb-sprof:start-profiling :threads (list sb-thread:*current-thread*)) |
| 113 | + (time (benchmark-one-quilc-perf-run program chip)) |
| 114 | + (sb-sprof:stop-profiling) |
| 115 | + (sb-sprof:report :type :graph :min-percent *min-sb-sprof-perf-pct*) |
| 116 | + (sb-sprof:report :type :flat :min-percent *min-sb-sprof-perf-pct*))) |
| 117 | + |
| 118 | +(defun do-one-mon (nq &optional program-type) |
| 119 | + (let ((program (build-benchmark-program nq (or program-type :hadamard))) |
| 120 | + (chip (build-benchmark-chip nq :fully-connected))) |
| 121 | + (tg:gc :full t) |
| 122 | + (sb-sprof:with-profiling (:max-samples 1000 |
| 123 | + :report :flat |
| 124 | + :loop nil |
| 125 | + |
| 126 | + :reset t |
| 127 | + :sample-interval 0.01) ; default .01 |
| 128 | + (benchmark-one-quilc-perf-run program chip)))) |
| 129 | + |
| 130 | + |
| 131 | + |
| 132 | +;;;; SB-SPROF Runs of Various Flavors |
| 133 | + |
| 134 | +(defparameter *default-sb-sprof-run-nqs* |
| 135 | + '(20 50 80 110) |
| 136 | + "Default list of nQ values for running various SB-SPROF calls below.") |
| 137 | + |
| 138 | +(defun sb-sprof-run () |
| 139 | + (loop :for nq :in *default-sb-sprof-run-nqs* |
| 140 | + :do (do-monitor-runs |
| 141 | + :start nq |
| 142 | + :monitor :sb-sprof |
| 143 | + :repeats 1 |
| 144 | + :report-type :flat))) |
| 145 | + |
| 146 | +(defun sb-sprof-graph () |
| 147 | + (loop :for nq :in *default-sb-sprof-run-nqs* |
| 148 | + :do (do-monitor-runs |
| 149 | + :start nq |
| 150 | + :monitor :sb-sprof |
| 151 | + :repeats 1 |
| 152 | + :report-type :flat))) |
| 153 | + |
| 154 | +(defun sb-sprof-run-high-sample () |
| 155 | + (loop :for nq :in *default-sb-sprof-run-nqs* |
| 156 | + :do (do-monitor-runs |
| 157 | + :start nq |
| 158 | + :monitor :sb-sprof |
| 159 | + :repeats 1 |
| 160 | + |
| 161 | + :sample-interval 0.001 ; our default: 0.005 |
| 162 | + :report-type :flat))) |
| 163 | + |
| 164 | +(defun sb-sprof-run-high-sample-plus-graph () |
| 165 | + (loop :for nq :in *default-sb-sprof-run-nqs* |
| 166 | + :do (do-monitor-runs |
| 167 | + :start nq |
| 168 | + :monitor :sb-sprof |
| 169 | + :repeats 1 |
| 170 | + |
| 171 | + :sample-interval 0.001 ; our default: 0.005 |
| 172 | + :report-type :graph))) ; our default: :flat |
| 173 | + |
| 174 | +(defun sb-sprof-run-mon () |
| 175 | + (loop :for nq :in *default-sb-sprof-run-nqs* |
| 176 | + :do (do-monitor-runs |
| 177 | + :start nq |
| 178 | + :monitor :mon |
| 179 | + :repeats 1 |
| 180 | + |
| 181 | + :sample-interval 0.001 ; our default: 0.005 |
| 182 | + :report-type :graph))) ; our default: :flat |
| 183 | + |
| 184 | +(defun one-monitor-run-bill-linear (nq) |
| 185 | + (monitor-run :bell :linear nq 1 :mon :flat .0001)) |
| 186 | + |
0 commit comments