Skip to content

Commit eee8d05

Browse files
author
whitequark
committedNov 9, 2016
doc: clarify kernel_invariant doc (fixes #609).
1 parent bfbdba9 commit eee8d05

File tree

1 file changed

+31
-3
lines changed

1 file changed

+31
-3
lines changed
 

‎doc/manual/compiler.rst

+31-3
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ If an RPC returns no value, it can be invoked in a way that does not block until
5454
execution, but only until it is queued. (Submitting asynchronous RPCs too rapidly, as well as
5555
submitting asynchronous RPCs with arguments that are too large, can still block until completion.)
5656

57-
To define an asynchronous RPC, use the ``@rpc`` annotation with a flag:
57+
To define an asynchronous RPC, use the ``@rpc`` annotation with a flag: ::
5858

5959
@rpc(flags={"async"})
6060
def record_result(x):
@@ -87,7 +87,7 @@ Kernel invariants
8787

8888
The compiler attempts to remove or hoist out of loops any redundant memory load operations, as well as propagate known constants into function bodies, which can enable further optimization. However, it must make conservative assumptions about code that it is unable to observe, because such code can change the value of the attribute, making the optimization invalid.
8989

90-
When an attribute is known to never change while the kernel is running, it can be marked as a *kernel invariant* to enable more aggressive optimization for this specific attribute: ::
90+
When an attribute is known to never change while the kernel is running, it can be marked as a *kernel invariant* to enable more aggressive optimization for this specific attribute. ::
9191

9292
class Converter:
9393
kernel_invariants = {"ratio"}
@@ -99,4 +99,32 @@ When an attribute is known to never change while the kernel is running, it can b
9999
def convert(self, value):
100100
return value * self.ratio ** 2
101101

102-
In the synthetic example above, the compiler will be able to detect that the result of evaluating ``self.ratio ** 2`` never changes and replace it with a constant, removing an expensive floating-point operation.
102+
In the synthetic example above, the compiler will be able to detect that the result of evaluating ``self.ratio ** 2`` never changes and replace it with a constant, removing an expensive floating-point operation. ::
103+
104+
class Worker:
105+
kernel_invariants = {"interval"}
106+
107+
def __init__(self, interval=1.0*us):
108+
self.interval = interval
109+
110+
def work(self):
111+
# something useful
112+
113+
class Looper:
114+
def __init__(self, worker):
115+
self.worker = worker
116+
117+
@kernel
118+
def loop(self):
119+
for _ in range(100):
120+
delay(self.worker.interval / 5.0)
121+
self.worker.work()
122+
123+
In the synthetic example above, the compiler will be able to detect that the result of evaluating ``self.interval / 5.0`` never changes, even though it neither knows the value of ``self.worker.interval`` beforehand nor can it see through the ``self.worker.work()`` function call, and hoist the expensive floating-point division out of the loop, transforming the code for ``loop`` into an equivalent of the following: ::
124+
125+
@kernel
126+
def loop(self):
127+
precomputed_delay_mu = seconds_to_mu(self.worker.interval / 5.0)
128+
for _ in range(100):
129+
delay_mu(precomputed_delay_mu)
130+
self.worker.work()

0 commit comments

Comments
 (0)
Please sign in to comment.