Part 1. One core · lesson 5 of 42
5. Commands¶
A command is one message from Python that makes cores run their kernels once. The kernels stay loaded on the cores between commands, so sending a command costs microseconds, not the seconds that loading costs. This lesson relies on lesson 4, Hello, core.
Why commands exist¶
A program that starts a kernel for every piece of work pays for the start every time: compile, copy to the cores, start. On this card that is seconds, and a piece of work on a core may take microseconds.
Komorebi pays once. load puts the three kernels on every core, and each core's run
loop (lesson 4) waits for commands. After that, each piece of work is a command: a short
message to cores that are already running and waiting.
Who sends it and how it travels¶
You call submit in Python. Python does not talk to the 120 cores one by one. It hands
the command to a program that Komorebi keeps running on one of the card's X280 cores,
the dispatcher. The dispatcher passes the command to the Tensix cores. When the cores
of the group are done, the dispatcher collects their reports into one, and wait returns
it as an event.
You do not write the dispatcher and you do not start it. load does that. What you need to
know is that it is there, and that it makes a command cheap.
What a command holds¶
A command is a small message. It holds a few things, and the next lessons add them one at a time. lesson 4, Hello, core used two of them:
- the kind of work, a number: lesson 8, Handlers,
- the group of cores that run it: lesson 11, A core group.
Three more come later: whether the cores send something back (lesson 6, A result), up to ten numbers for the kernel to work with (lesson 7, Arguments) and a few settings that Part 2 and later parts use.
See it cost microseconds¶
The program below loads the kernels once and measures it, then sends the same command three times. It uses the kernels of lesson 4 unchanged; only the Python file is new.
started = time.perf_counter()
run = session.load(program)
print(f"loading the kernels took {time.perf_counter() - started:.2f} seconds")
time.perf_counter() is Python's clock. These lines measure how long load takes.
for number in (1, 2, 3):
handle = run.submit(0, group=(0, 1))
event = run.wait(handle, timeout=10.0)
micros = event.microseconds
print(f"command {number}: {event.kind} after {micros:.1f} microseconds")
Three commands, one after the other: send, wait for the event, print. event.microseconds is how
long the command took, in microseconds, from the moment it was submitted until the event
was ready, measured on the card.
"""Commands: the kernels are loaded once; each command only costs microseconds."""
import time
from pathlib import Path
import komorebi as km
HERE = Path(__file__).resolve().parent
program = km.Program("commands", kernels=HERE / "kernels")
with km.Session() as session:
started = time.perf_counter()
run = session.load(program)
print(f"loading the kernels took {time.perf_counter() - started:.2f} seconds")
for number in (1, 2, 3):
handle = run.submit(0, group=(0, 1))
event = run.wait(handle, timeout=10.0)
micros = event.microseconds
print(f"command {number}: {event.kind} after {micros:.1f} microseconds")
run.stop()
The other two kernel files are the same empty ones as in lesson 4.
loading the kernels took 1.11 seconds
command 1: done after 2.2 microseconds
command 2: done after 1.6 microseconds
command 3: done after 1.7 microseconds
The times are from one run and differ on every run. What does not differ is the proportion: loading takes a second, about 1,000,000 microseconds, and a command takes about two. The first run after you change a kernel file takes longer, because the C++ has to be compiled.
Common mistakes¶
- Loading again for every piece of work. Put
loadbefore the loop andsubmitinside it. - Sending a command after
stop. It is refused withKomorebiError: the run is stopped. A run ends atstop; to run again,loadagain. - Expecting
submitto wait. It returns at once. The command may not have started whensubmitreturns;waitis what waits for it.
Next: lesson 6, A result makes the core send a number back.