Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make chip-contiguous-subschedule-from-last-instructions non-recursive #693

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 26 additions & 44 deletions src/addresser/outgoing-schedule.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -108,54 +108,36 @@ BEFORE-INST to make use of RESOURCE."
:when (carving-point-p resource instr)
:maximize (chip-schedule-end-time schedule instr)))

(defun chip-schedule-from-carving-point (schedule resource point)
"Returns the (time-ordered) subsequence of instructions from SCHEDULE which intersect RESOURCE and which start on or after the time POINT.

If POINT is generated by CHIP-SCHEDULE-RESOURCE-CARVING-POINT, then the resulting subsequence has a further \"information light-cone\" property: SCHEDULE will have no other instructions which can receive information from RESOURCE from after POINT."
;; NOTE: This could be written in such a way that GETHASH is called only once:
;; grab it inside of LOOP and attach it to INSTR by a CONS cell, then
;; change SORT's KEY to grab that value, then strip the cells away at end.
(sort
(loop :for instr :being :the :hash-keys :of (chip-schedule-times schedule)
:when (and (<= point (chip-schedule-start-time schedule instr))
(resources-intersect-p resource (instruction-resources instr)))
:collect instr)
#'<
:key (lambda (i) (gethash i (chip-schedule-times schedule)))))

;; TODO Make this non-recursive so we can avoid blowing the stack on
;; veeeerrrrry deep programs.
(defun chip-contiguous-subschedule-from-last-instructions (schedule resource)
"Returns an unordered contiguous subsequence of instructions from SCHEDULE where each instruction is in the dependency graph of the last instructions in SCHEDULE and touches only resources in RESOURCE."
(defun mark-predecessors-seen (instr earlier-instrs seen)
"Performs a depth first search on INSTR as the root node and marks all of its descendants as true in hash-table SEEN."
(let ((stack (list instr)))
(loop :while stack :do
(let ((predecessors (gethash (pop stack) earlier-instrs)))
(dolist (predecessor predecessors)
(unless (gethash predecessor seen)
(setf (gethash predecessor seen) t)
(push predecessor stack)))))))

(defun chip-contiguous-subschedule-from-last-instructions (schedule resource)
"Returns an unordered list of instructions from SCHEDULE such that each instruction involves a subset of RESOURCE. Traversal of the schedule begins from the latest scheduled instructions and works backwards into earlier instructions until an instruction uses resources not in RESOURCE."
(let* ((lsched (chip-schedule-data schedule))
(last-instrs (lscheduler-last-instrs lsched))
(earlier-instrs (lscheduler-earlier-instrs lsched))
(seen (make-hash-table))
(leaves (lscheduler-last-instrs lsched))
(sched nil))
(labels ((mark-predecessors-seen (instr)
(cond ((resource= (instruction-resources instr)
resource)
(setf (gethash instr seen) t))
((resource-subsetp (instruction-resources instr)
resource)
(map nil #'mark-predecessors-seen (gethash instr earlier-instrs)))))
(bottoms-up (instr)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was nice while it lasted 🍻

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🍻

;; Recursively explorer earlier instructions in the
;; schedule. Instructions are collected if their
;; resources are a subset of RESOURCE. If a carving
;; point is encountered, mark all earlier instructions
;; as seen.
(unless (gethash instr seen)
(setf (gethash instr seen) t)
(cond
((carving-point-p resource instr)
(map nil #'mark-predecessors-seen (reverse (gethash instr earlier-instrs))))
((and (resources-intersect-p resource (instruction-resources instr))
(not (carving-point-p resource instr)))
(push instr sched)
(map nil #'bottoms-up (reverse (gethash instr earlier-instrs))))))))
(map nil #'bottoms-up last-instrs)
sched)))
(loop :while leaves :do
(let ((instr (pop leaves)))
erichulburd marked this conversation as resolved.
Show resolved Hide resolved
(unless (gethash instr seen)
(setf (gethash instr seen) t)
(cond
((and (resources-intersect-p resource (instruction-resources instr))
(resource-subsetp (instruction-resources instr) resource))
(push instr sched)
(dolist (earlier-instr (gethash instr earlier-instrs))
(push earlier-instr leaves)))
erichulburd marked this conversation as resolved.
Show resolved Hide resolved
((carving-point-p resource instr)
(mark-predecessors-seen instr earlier-instrs seen))))))
sched))

(defun chip-schedule-qubit-times (schedule)
"Find the first time a qubit is available, for each qubit in the schedule."
Expand Down
23 changes: 23 additions & 0 deletions tests/addresser-tests.lisp
Original file line number Diff line number Diff line change
Expand Up @@ -100,3 +100,26 @@
(quil::chip-contiguous-subschedule-from-last-instructions
sched (quil::make-qubit-resource 0 2))
expected-subschedule))))))

(deftest test-fidelity-addresser-subschedule-on-deep-circuit ()
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can confirm this spec will result in control stack exhaustion with old implementation:

Screen Shot 2021-01-27 at 11 32 38 AM (2)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we gotta work on your emacs theme at some point

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All I really care about is ENORMOUS FONT. Otherwise, I'm open.

(let* ((chip (quil::build-nq-fully-connected-chip 3))
(sched (quil::make-chip-schedule chip))
(h0 (build-gate "H" nil 0))
(circuit-depth 25000))
(loop :for i :from 1 :to circuit-depth :do
(progn
;; these gates will exercise depth in the outer dfs, ie in
;; chip-contiguous-subschedule-from-last-instructions.
(quil::chip-schedule-append sched (build-gate "H" nil 0))
;; these gates will exercise depth in the inner dfs, ie in
;; mark-predecessors-seen.
(quil::chip-schedule-append sched (build-gate "H" nil 1))))
(flet ((is-h0 (gate)
(and (string= (quil::application-operator-root-name gate)
(quil::application-operator-root-name h0))
(equalp (quil::application-parameters gate)
(quil::application-parameters h0)))))
(let ((result (quil::chip-contiguous-subschedule-from-last-instructions sched (quil::make-qubit-resource 0))))
(is (= (length result) circuit-depth))
(is (every #'is-h0 result))))))