forked from M-Labs/artiq
core: compile and upload subkernels
This commit is contained in:
parent
8d7194941e
commit
973fd88b27
|
@ -23,6 +23,8 @@ class Request(Enum):
|
||||||
RPCReply = 7
|
RPCReply = 7
|
||||||
RPCException = 8
|
RPCException = 8
|
||||||
|
|
||||||
|
SubkernelUpload = 9
|
||||||
|
|
||||||
|
|
||||||
class Reply(Enum):
|
class Reply(Enum):
|
||||||
SystemInfo = 2
|
SystemInfo = 2
|
||||||
|
@ -208,6 +210,7 @@ class CommKernel:
|
||||||
self.unpack_float64 = struct.Struct(self.endian + "d").unpack
|
self.unpack_float64 = struct.Struct(self.endian + "d").unpack
|
||||||
|
|
||||||
self.pack_header = struct.Struct(self.endian + "lB").pack
|
self.pack_header = struct.Struct(self.endian + "lB").pack
|
||||||
|
self.pack_int8 = struct.Struct(self.endian + "B").pack
|
||||||
self.pack_int32 = struct.Struct(self.endian + "l").pack
|
self.pack_int32 = struct.Struct(self.endian + "l").pack
|
||||||
self.pack_int64 = struct.Struct(self.endian + "q").pack
|
self.pack_int64 = struct.Struct(self.endian + "q").pack
|
||||||
self.pack_float64 = struct.Struct(self.endian + "d").pack
|
self.pack_float64 = struct.Struct(self.endian + "d").pack
|
||||||
|
@ -322,7 +325,7 @@ class CommKernel:
|
||||||
self._write(chunk)
|
self._write(chunk)
|
||||||
|
|
||||||
def _write_int8(self, value):
|
def _write_int8(self, value):
|
||||||
self._write(value)
|
self._write(self.pack_int8(value))
|
||||||
|
|
||||||
def _write_int32(self, value):
|
def _write_int32(self, value):
|
||||||
self._write(self.pack_int32(value))
|
self._write(self.pack_int32(value))
|
||||||
|
@ -382,6 +385,19 @@ class CommKernel:
|
||||||
else:
|
else:
|
||||||
self._read_expect(Reply.LoadCompleted)
|
self._read_expect(Reply.LoadCompleted)
|
||||||
|
|
||||||
|
def upload_subkernel(self, kernel_library, id, destination):
|
||||||
|
self._write_header(Request.SubkernelUpload)
|
||||||
|
self._write_int32(id)
|
||||||
|
self._write_int8(destination)
|
||||||
|
self._write_bytes(kernel_library)
|
||||||
|
self._flush()
|
||||||
|
|
||||||
|
self._read_header()
|
||||||
|
if self._read_type == Reply.LoadFailed:
|
||||||
|
raise LoadError(self._read_string())
|
||||||
|
else:
|
||||||
|
self._read_expect(Reply.LoadCompleted)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
self._write_empty(Request.RunKernel)
|
self._write_empty(Request.RunKernel)
|
||||||
self._flush()
|
self._flush()
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import os, sys
|
import os, sys
|
||||||
import numpy
|
import numpy
|
||||||
|
from inspect import getfullargspec
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
|
|
||||||
from pythonparser import diagnostic
|
from pythonparser import diagnostic
|
||||||
|
@ -103,12 +104,13 @@ class Core:
|
||||||
|
|
||||||
def compile(self, function, args, kwargs, set_result=None,
|
def compile(self, function, args, kwargs, set_result=None,
|
||||||
attribute_writeback=True, print_as_rpc=True,
|
attribute_writeback=True, print_as_rpc=True,
|
||||||
target=None):
|
target=None, destination=0, subkernel_arg_types=[]):
|
||||||
try:
|
try:
|
||||||
engine = _DiagnosticEngine(all_errors_are_fatal=True)
|
engine = _DiagnosticEngine(all_errors_are_fatal=True)
|
||||||
|
|
||||||
stitcher = Stitcher(engine=engine, core=self, dmgr=self.dmgr,
|
stitcher = Stitcher(engine=engine, core=self, dmgr=self.dmgr,
|
||||||
print_as_rpc=print_as_rpc)
|
print_as_rpc=print_as_rpc,
|
||||||
|
destination=destination, subkernel_arg_types=subkernel_arg_types)
|
||||||
stitcher.stitch_call(function, args, kwargs, set_result)
|
stitcher.stitch_call(function, args, kwargs, set_result)
|
||||||
stitcher.finalize()
|
stitcher.finalize()
|
||||||
|
|
||||||
|
@ -122,7 +124,8 @@ class Core:
|
||||||
|
|
||||||
return stitcher.embedding_map, stripped_library, \
|
return stitcher.embedding_map, stripped_library, \
|
||||||
lambda addresses: target.symbolize(library, addresses), \
|
lambda addresses: target.symbolize(library, addresses), \
|
||||||
lambda symbols: target.demangle(symbols)
|
lambda symbols: target.demangle(symbols), \
|
||||||
|
module.subkernel_arg_types
|
||||||
except diagnostic.Error as error:
|
except diagnostic.Error as error:
|
||||||
raise CompileError(error.diagnostic) from error
|
raise CompileError(error.diagnostic) from error
|
||||||
|
|
||||||
|
@ -140,11 +143,32 @@ class Core:
|
||||||
def set_result(new_result):
|
def set_result(new_result):
|
||||||
nonlocal result
|
nonlocal result
|
||||||
result = new_result
|
result = new_result
|
||||||
embedding_map, kernel_library, symbolizer, demangler = \
|
embedding_map, kernel_library, symbolizer, demangler, subkernel_arg_types = \
|
||||||
self.compile(function, args, kwargs, set_result)
|
self.compile(function, args, kwargs, set_result)
|
||||||
|
self.compile_subkernels(embedding_map, args, subkernel_arg_types)
|
||||||
self._run_compiled(kernel_library, embedding_map, symbolizer, demangler)
|
self._run_compiled(kernel_library, embedding_map, symbolizer, demangler)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
def compile_subkernels(self, embedding_map, args, subkernel_arg_types):
|
||||||
|
for sid, subkernel_fn in embedding_map.subkernels().items():
|
||||||
|
# pass self to subkernels (if applicable)
|
||||||
|
# assuming the first argument is self
|
||||||
|
subkernel_args = getfullargspec(subkernel_fn.artiq_embedded.function)
|
||||||
|
self_arg = []
|
||||||
|
if len(subkernel_args[0]) > 0:
|
||||||
|
if subkernel_args[0][0] == 'self':
|
||||||
|
self_arg = args[:1]
|
||||||
|
destination = subkernel_fn.artiq_embedded.destination
|
||||||
|
destination_tgt = self.dmgr.ddb.get_satellite_cpu_target(destination)
|
||||||
|
target = get_target_cls(destination_tgt)(subkernel_id=sid)
|
||||||
|
object_map, kernel_library, _, _, _ = \
|
||||||
|
self.compile(subkernel_fn, self_arg, {}, attribute_writeback=False,
|
||||||
|
print_as_rpc=False, target=target, destination=destination,
|
||||||
|
subkernel_arg_types=subkernel_arg_types.get(sid, []))
|
||||||
|
if object_map.has_rpc_or_subkernel():
|
||||||
|
raise ValueError("Subkernel must not use RPC or subkernels in other destinations")
|
||||||
|
self.comm.upload_subkernel(kernel_library, sid, destination)
|
||||||
|
|
||||||
def precompile(self, function, *args, **kwargs):
|
def precompile(self, function, *args, **kwargs):
|
||||||
"""Precompile a kernel and return a callable that executes it on the core device
|
"""Precompile a kernel and return a callable that executes it on the core device
|
||||||
at a later time.
|
at a later time.
|
||||||
|
@ -153,7 +177,7 @@ class Core:
|
||||||
as additional positional and keyword arguments.
|
as additional positional and keyword arguments.
|
||||||
The returned callable accepts no arguments.
|
The returned callable accepts no arguments.
|
||||||
|
|
||||||
Precompiled kernels may use RPCs.
|
Precompiled kernels may use RPCs and subkernels.
|
||||||
|
|
||||||
Object attributes at the beginning of a precompiled kernel execution have the
|
Object attributes at the beginning of a precompiled kernel execution have the
|
||||||
values they had at precompilation time. If up-to-date values are required,
|
values they had at precompilation time. If up-to-date values are required,
|
||||||
|
@ -178,8 +202,9 @@ class Core:
|
||||||
nonlocal result
|
nonlocal result
|
||||||
result = new_result
|
result = new_result
|
||||||
|
|
||||||
embedding_map, kernel_library, symbolizer, demangler = \
|
embedding_map, kernel_library, symbolizer, demangler, subkernel_arg_types = \
|
||||||
self.compile(function, args, kwargs, set_result, attribute_writeback=False)
|
self.compile(function, args, kwargs, set_result, attribute_writeback=False)
|
||||||
|
self.compile_subkernels(embedding_map, args, subkernel_arg_types)
|
||||||
|
|
||||||
@wraps(function)
|
@wraps(function)
|
||||||
def run_precompiled():
|
def run_precompiled():
|
||||||
|
|
|
@ -148,6 +148,13 @@ class DMAError(Exception):
|
||||||
artiq_builtin = True
|
artiq_builtin = True
|
||||||
|
|
||||||
|
|
||||||
|
class SubkernelError(Exception):
|
||||||
|
"""Raised when an operation regarding a subkernel is invalid
|
||||||
|
or cannot be completed.
|
||||||
|
"""
|
||||||
|
artiq_builtin = True
|
||||||
|
|
||||||
|
|
||||||
class ClockFailure(Exception):
|
class ClockFailure(Exception):
|
||||||
"""Raised when RTIO PLL has lost lock."""
|
"""Raised when RTIO PLL has lost lock."""
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,9 @@ class DeviceDB:
|
||||||
desc = self.data.raw_view[desc]
|
desc = self.data.raw_view[desc]
|
||||||
return desc
|
return desc
|
||||||
|
|
||||||
|
def get_satellite_cpu_target(self, destination):
|
||||||
|
return self.data.raw_view["satellite_cpu_targets"][destination]
|
||||||
|
|
||||||
|
|
||||||
class DatasetDB(TaskObject):
|
class DatasetDB(TaskObject):
|
||||||
def __init__(self, persist_file, autosave_period=30):
|
def __init__(self, persist_file, autosave_period=30):
|
||||||
|
|
Loading…
Reference in New Issue