.. _sdkruntime-api-reference: SdkRuntime API Reference ======================== This section presents the ``SdkRuntime`` Python host API reference and associated utilities to develop kernels for the Cerebras Wafer-Scale Engine. sdkruntimepybind module ----------------------- .. py:module:: cerebras.sdk.runtime.sdkruntimepybind Python API for ``SdkRuntime`` functions. MemcpyDataType ^^^^^^^^^^^^^^ .. py:class:: MemcpyDataType :module: cerebras.sdk.runtime.sdkruntimepybind Bases: :class:`Enum` Specifies the data size for transfers using :py:meth:`SdkRuntime.memcpy_d2h` and :py:meth:`SdkRuntime.memcpy_h2d` copy mode. :Values: * **MEMCPY_16BIT** * **MEMCPY_32BIT** MemcpyOrder ^^^^^^^^^^^ .. py:class:: MemcpyOrder :module: cerebras.sdk.runtime.sdkruntimepybind Bases: :class:`Enum` Specifies mapping of data for transfers using :py:meth:`SdkRuntime.memcpy_d2h` and :py:meth:`SdkRuntime.memcpy_h2d` copy mode. :Values: * **ROW_MAJOR** * **COL_MAJOR** SdkCompileArtifacts ^^^^^^^^^^^^^^^^^^^ .. py:class:: SdkCompileArtifacts(artifacts_path: str) :module: cerebras.sdk.runtime.sdkruntimepybind Bases: :class:`object` Specifies compile artifacts for execution. :param artifacts_path: Path to compile artifacts. :type artifacts_path: ``str`` SdkExecutionPlatform ^^^^^^^^^^^^^^^^^^^^ .. py:class:: SdkExecutionPlatform :module: cerebras.sdk.runtime.sdkruntimepybind Bases: :class:`object` Specifies the simulator or system target and architecture for execution. .. py:method:: is_simulation() :module: cerebras.sdk.runtime.sdkruntimepybind Queries if the execution platform is a simulator. :returns: ``True`` if the execution platform is a simulator, ``False`` otherwise. :rtype: ``bool`` .. py:method:: is_system() :module: cerebras.sdk.runtime.sdkruntimepybind Queries if the execution platform is a real system. :returns: ``True`` if the execution platform is a real system, ``False`` otherwise. :rtype: ``bool`` SdkRuntime ^^^^^^^^^^ .. py:class:: SdkRuntime(bindir: Union[pathlib.Path, str], **kwargs) :module: cerebras.sdk.runtime.sdkruntimepybind Bases: :class:`object` Manages the execution of SDK programs on the Cerebras Wafer Scale Engine (WSE) or simfabric. The constructor analyzes the WSE ELFs in the ``bindir`` and prepares the WSE or simfabric for a run. Requires CM IP address and port for WSE runs. :param bindir: Path to ELF files which is compiled by ``cslc``. The runtime collects the I/O and fabric parameters automatically, including height, width, number of channels, width of buffers,... etc. :type bindir: ``Union[pathlib.Path, str]`` :Keyword Arguments: * **cmaddr** (``str``) -- ``'IP_ADDRESS:PORT'`` string of CM. Omit this ``kwarg`` to run on simfabric. * **suppress_simfab_trace** (``bool``) -- If ``True``, suppresses generation of ``simfab_traces`` when running. Default value is ``False``, i.e., ``simfab_traces`` are produced. * **simfab_numthreads** (``int``) -- Number of threads to use if running on simfabric. Maximum value is ``64``. Default value is ``5``, i.e., the simulator uses 5 threads. * **msg_level** (``str``) -- Message logging output level. Available output levels are ``DEBUG``, ``INFO``, ``WARNING``, and ``ERROR``. Default value is ``WARNING``. **Example**: In the following example, an ``SdkRuntime`` runner object is instantiated. If ``args.cmaddr`` is non-empty, then the kernel code will run on the WSE pointed to by that address; otherwise, the kernel code will run on simfabric. The compiled kernel code in the directory ``args.name`` has exported symbols ``A`` and ``B`` pointing to arrays on the device. After loading the code and starting the run with ``load()`` and ``run()``, data on the host stored in ``data`` is copied to ``A`` on the device, and then ``B`` on the device is copied back into ``data`` on the host. .. code-block:: python runner = SdkRuntime(args.name, cmaddr=args.cmaddr) symbol_A = runner.get_id("A") symbol_B = runner.get_id("B") runner.load() runner.run() runner.memcpy_h2d(symbol_A, data, px, py, w, h, l, streaming=False, data_type=memcpy_dtype, order=memcpy_order, nonblock=False) runner.memcpy_d2h(data, symbol_B, px, py, w, h, l, streaming=False, data_type=memcpy_dtype, order=memcpy_order, nonblock=False) .. py:method:: __init__(bindir: Union[pathlib.Path, str], platform: SdkExecutionPlatform, **kwargs) -> None :module: cerebras.sdk.runtime.sdkruntimepybind Constructor variant that takes a path to compiled ELF files and an execution platform specification. Takes same kwargs as above. .. py:method:: __init__(artifacts: SdkCompileArtifacts, platform: SdkExecutionPlatform, **kwargs) -> None :module: cerebras.sdk.runtime.sdkruntimepybind :noindex: Constructor variant that takes a compile artifacts specification and execution platform specification. Takes same kwargs as above. .. py:method:: SdkRuntime.coord_logical_to_physical(logical_coords: (int, int)) :module: cerebras.sdk.runtime.sdkruntimepybind Convert a logical coordinate to a physical coordinate. For a program with fabric offsets (``offset_x``, ``offset_y``), and program rectangle coordinate (``x``, ``y``), this function returns (``offset_x + x``, ``offset_y + y``). :param logical_coords: Tuple containing logical coordinates. :type symbol: ``(int, int)`` :returns: Tuple containing physical coordinates. :rtype: ``(int, int)`` .. py:method:: SdkRuntime.dump_core(corefile: str) :module: cerebras.sdk.runtime.sdkruntimepybind Dump the core of a simulator run, to be used for debugging with ``csdb``. Note that the specified name of the corefile MUST be "corefile.cs1" to use with ``csdb``, and this method can only be called after a blocking :py:class:`SdkRuntime` API call, or after calling :py:meth:`SdkRuntime.stop`. :param corefile: Name of corefile. Must be "corefile.cs1" to use with ``csdb``. :type symbol: ``str`` .. py:method:: get_id(symbol: str) -> int :module: cerebras.sdk.runtime.sdkruntimepybind Retrieve the integer representation of an exported symbol which is exported in the kernel. Possible symbols include a data tensor or a host-callable function. :param symbol: The exported name of the symbol. :type symbol: ``str`` :returns: Integer representation of exported symbol :rtype: ``int`` .. py:method:: get_port_id(port_name: str) -> PortId :module: cerebras.sdk.runtime.sdkruntimepybind Part of the :py:class:`SdkRuntime` direct link API. Retrieve the integer representation of a program port for streaming data via :py:meth:`SdkRuntime.send` or :py:meth:`SdkRuntime.receive`. :param symbol: The exported name of the symbol. :type symbol: ``str`` :returns: Integer representation of program data port. :rtype: ``PortId`` .. py:method:: is_task_done(task_handle: Task) -> bool :module: cerebras.sdk.runtime.sdkruntimepybind Query if task ``task_handle`` is complete. :param task_handle: Handle to a task previously launched by :py:class:`SdkRuntime`. :type task_handle: :py:class:`Task` :returns: ``True`` if task is done, and ``False`` otherwise. :rtype: ``bool`` .. py:method:: launch(symbol: str, *args, **kwargs) -> Task :module: cerebras.sdk.runtime.sdkruntimepybind Trigger a host-callable function defined in the kernel, with type checking for arguments. :param symbol: The exported name of the symbol corresponding to a host-callable function. :type symbol: ``str`` :Positional Arguments: Matches the arguments of the host-callable function. :py:meth:`SdkRuntime.launch` will perform type checking on the arguments. :Keyword Arguments: **nonblock** (``bool``) -- Nonblocking if ``True``, blocking otherwise. :returns: Handle to the task launched by :py:meth:`SdkRuntime.launch`. :rtype: :py:class:`Task` **Example**: Consider a kernel which defines a host-callable function ``fn_foo`` by: .. code-block:: csl comptime { @export_symbol(fn_foo); } The host calls ``fn_foo`` by ``runner.launch("fn_foo", nonblock=False)``. .. py:method:: load() :module: cerebras.sdk.runtime.sdkruntimepybind Load the binaries to simfabric or WSE. It may takes 80+ seconds to load the binaries onto the WSE. .. py:method:: memcpy_d2h(dest: numpy.ndarray, src: int, px: int, py: int, w: int, h: int, elem_per_pe: int, **kwargs) -> Task :module: cerebras.sdk.runtime.sdkruntimepybind Receive a host tensor from the device. The data is received from the region of interest (ROI) which is a bounding box starting at coordinate ``(px, py)`` with width ``w`` and height ``h``. :param dest: A 3-D host tensor ``A[h][w][elem_per_pe]``, wrapped in a 1-D array according to keyword argument ``order``. :type dest: ``numpy.ndarray`` :param src: A user-defined color if keyword argument ``streaming=True``, symbol of a device tensor otherwise. :type src: ``int`` :param px: ``x``-coordinate of start point of the ROI. :type px: ``int`` :param py: ``y``-coordinate of start point of the ROI. :type py: ``int`` :param w: Width of the ROI. :type w: ``int`` :param h: Height of the ROI. :type h: ``int`` :param elem_per_pe: Number of elements per PE. The data type of an element is 16-bit and 32-bit only. If the tensor has ``k`` elements per PE, ``elem_per_pe`` is ``k`` even if the data type is 16-bit. If the data type is 16-bit, the user has to extend the tensor to a 32-bit one, with zero filled in the higher 16 bits. :type elem_per_pe: ``int`` :Keyword Arguments: * **streaming** (``bool``) -- Streaming mode if ``True``, copy mode otherwise. * **data_type** (:py:class:`MemcpyDataType`) -- 32-bit if ``MemcpyDataType.MEMCPY_32BIT`` or 16-bit if ``MemcpyDataType.MEMCPY_16BIT``. Note that this argument has no effect if ``streaming`` is ``True``, and the user must handle the data appropriately in the receiving wavelet-triggered task. Additionally, the underlying type of the tensor ``dest`` must be 32-bit. The tensor must be extended to a 32-bit one with zero filled in the higher 16 bits. * **order** (:py:class:`MemcpyOrder`) -- Row-major if ``MemcpyOrder.ROW_MAJOR`` or column-major if ``MemcpyOrder.COL_MAJOR``. * **nonblock** (``bool``) -- Nonblocking if ``True``, blocking otherwise. :returns: Handle to the task launched by :py:meth:`SdkRuntime.memcpy_d2h`. :rtype: :py:class:`Task` .. py:method:: memcpy_h2d(dest: int, src: numpy.ndarray, px: int, py: int, w: int, h: int, elem_per_pe: int, **kwargs) -> Task :module: cerebras.sdk.runtime.sdkruntimepybind Send a host tensor to the device. The data is distributed into the region of interest (ROI) which is a bounding box starting at coordinate ``(px, py)`` with width ``w`` and height ``h``. :param dest: A user-defined color if keyword argument ``streaming=True``, symbol of a device tensor otherwise. :type dest: ``int`` :param src: A 3-D host tensor ``A[h][w][elem_per_pe]``, wrapped in a 1-D array according to parameter ``order``. :type src: ``numpy.ndarray`` :param px: ``x``-coordinate of start point of the ROI. :type px: ``int`` :param py: ``y``-coordinate of start point of the ROI. :type py: ``int`` :param w: Width of the ROI. :type w: ``int`` :param h: Height of the ROI. :type h: ``int`` :param elem_per_pe: Number of elements per PE. The data type of an element is 16-bit and 32-bit only. If the tensor has ``k`` elements per PE, ``elem_per_pe`` is ``k`` even if the data type is 16-bit. If the data type is 16-bit, the user has to extend the tensor to a 32-bit one, with zero filled in the higher 16 bits. :type elem_per_pe: ``int`` :Keyword Arguments: See :py:meth:`SdkRuntime.memcpy_d2h` keyword arguments. :returns: Handle to the task launched by :py:meth:`SdkRuntime.memcpy_h2d`. :rtype: :py:class:`Task` .. py:method:: memcpy_h2d_colbcast(dest: int, src: numpy.ndarray, px: int, py: int, w: int, h: int, elem_per_pe: int, **kwargs) -> Task :module: cerebras.sdk.runtime.sdkruntimepybind Broadcast a row of host data down columns of PEs. The data is distributed across the first row in the region of interest (ROI), which is a bounding box starting at coordinate ``(px, py)`` with width ``w`` and height ``h``, and then broadcast down each column of the ROI. :param dest: A user-defined color if keyword argument ``streaming=True``, symbol of a device tensor otherwise. :type dest: ``int`` :param src: A 2-D host tensor ``A[w][elem_per_pe]``, wrapped in a 1-D array according to parameter ``order``. :type src: ``numpy.ndarray`` :param px: ``x``-coordinate of start point of the ROI. :type px: ``int`` :param py: ``y``-coordinate of start point of the ROI. :type py: ``int`` :param w: Width of the ROI. :type w: ``int`` :param h: Height of the ROI. :type h: ``int`` :param elem_per_pe: Number of elements per PE. The data type of an element is 16-bit and 32-bit only. If the tensor has ``k`` elements per PE, ``elem_per_pe`` is ``k`` even if the data type is 16-bit. If the data type is 16-bit, the user has to extend the tensor to a 32-bit one, with zero filled in the higher 16 bits. :type elem_per_pe: ``int`` :Keyword Arguments: See :py:meth:`SdkRuntime.memcpy_d2h` keyword arguments. :returns: Handle to the task launched by :py:meth:`SdkRuntime.memcpy_h2d_colbcast`. :rtype: :py:class:`Task` .. py:method:: memcpy_h2d_rowbcast(dest: int, src: numpy.ndarray, px: int, py: int, w: int, h: int, elem_per_pe: int, **kwargs) -> Task :module: cerebras.sdk.runtime.sdkruntimepybind Broadcast a column of host data across rows of PEs. The data is distributed across the first column in the region of interest (ROI), which is a bounding box starting at coordinate ``(px, py)`` with width ``w`` and height ``h``, and then broadcast down each column of the ROI. :param dest: A user-defined color if keyword argument ``streaming=True``, symbol of a device tensor otherwise. :type dest: ``int`` :param src: A 2-D host tensor ``A[h][elem_per_pe]``, wrapped in a 1-D array according to parameter ``order``. :type src: ``numpy.ndarray`` :param px: ``x``-coordinate of start point of the ROI. :type px: ``int`` :param py: ``y``-coordinate of start point of the ROI. :type py: ``int`` :param w: Width of the ROI. :type w: ``int`` :param h: Height of the ROI. :type h: ``int`` :param elem_per_pe: Number of elements per PE. The data type of an element is 16-bit and 32-bit only. If the tensor has ``k`` elements per PE, ``elem_per_pe`` is ``k`` even if the data type is 16-bit. If the data type is 16-bit, the user has to extend the tensor to a 32-bit one, with zero filled in the higher 16 bits. :type elem_per_pe: ``int`` :Keyword Arguments: See :py:meth:`SdkRuntime.memcpy_d2h` keyword arguments. :returns: Handle to the task launched by :py:meth:`SdkRuntime.memcpy_h2d_rowbcast`. :rtype: :py:class:`Task` .. py:method:: memcpy_h2d_stride(dest: int, src: numpy.ndarray, px: int, py: int, w: int, h: int, elem_per_pe: int, row_stride: int, col_stride: int, **kwargs) -> Task :module: cerebras.sdk.runtime.sdkruntimepybind Send a host tensor to the device with a stride pattern across receiving PEs. The data is distributed into the region of interest (ROI) which is a bounding box starting at coordinate ``(px, py)`` with width ``w`` and height ``h``. Across a given row, ``row_stride`` determines the stride between receiving PEs within the ROI, and across a given column, ``col_stride`` determines the stride between receiving PEs. The first row and column to which data is sent is given by the PE ``(px, py)`` at the top-left of the ROI. We denote by ``xi`` and ``eta`` the number of columns and rows to which elements will be sent in the ROI, respectively. Since the ROI is ``w`` PEs wide and ``h`` PEs tall, ``xi`` and ``eta`` are given by ``xi = 1 + floor((w - 1) / row_stride)`` and ``eta = 1 + floor((h - 1) / col_stride)``. As an example, consider an ROI starting at (0, 0) with width 6 and height 8, and row and column strides 3 and 2, respectively. Then PEs with x coordinate 0 or 3 and y coordinate 0, 2, 4, 6 will receive data from the host. In this case, ``xi = 2`` and ``eta = 4``. :param dest: A user-defined color if keyword argument ``streaming=True``, symbol of a device tensor otherwise. :type dest: ``int`` :param src: A 3-D host tensor ``A[xi][eta][elem_per_pe]``, wrapped in a 1-D array according to parameter ``order``. :type src: ``numpy.ndarray`` :param px: ``x``-coordinate of start point of the ROI. :type px: ``int`` :param py: ``y``-coordinate of start point of the ROI. :type py: ``int`` :param w: Width of the ROI. :type w: ``int`` :param h: Height of the ROI. :type h: ``int`` :param elem_per_pe: Number of elements per PE. The data type of an element is 16-bit and 32-bit only. If the tensor has ``k`` elements per PE, ``elem_per_pe`` is ``k`` even if the data type is 16-bit. If the data type is 16-bit, the user has to extend the tensor to a 32-bit one, with zero filled in the higher 16 bits. :type elem_per_pe: ``int`` :param row_stride: Stride between PEs within a row in the ROI. Since the ROI is ``w`` PEs wide, the number of columns to which elements will be sent is ``xi = 1 + floor((w - 1) / row_stride)``. :type row_stride: ``int`` :param col_stride: Stride between PEs within a column in the ROI. Since the ROI is ``h`` PEs tall, the number of rows to which elements will be sent is ``eta = 1 + floor((h - 1) / col_stride)``. :type row_stride: ``int`` :Keyword Arguments: See :py:meth:`SdkRuntime.memcpy_d2h` keyword arguments. :returns: Handle to the task launched by :py:meth:`SdkRuntime.memcpy_h2d_stride`. :rtype: :py:class:`Task` .. py:method:: receive(port: Union[PortId, str], dest: numpy.ndarray, n_wavelets: int, **kwargs) -> Task :module: cerebras.sdk.runtime.sdkruntime.pybind Part of the py:class`SdkRuntime` direct link API. Receive ``n_wavelets`` wavelets via the program port ``port`` into array ``dest``. :param port: Program port from which data will be received. Can be specified by a numerical port ID or by name. :type port: ``Union[PortId, str]`` :param dest: Destination array into which the data will be received. :type dest: ``numpy.ndarray``. :param n_wavelets: Number of wavelets to receive. :type n_wavelets: ``int`` :Keyword Arguments: * **nonblock** (``bool``) -- Nonblocking if ``True``, blocking otherwise. :returns: Handle to the task launched by :py:meth:`SdkRuntime.receive`. :rtype: :py:class:`Task` .. py:method:: receive_tofile(port: Union[PortId, str], outfile: str, **kwargs) -> Task :module: cerebras.sdk.runtime.sdkruntime.pybind Part of the :py:class:`SdkRuntime` direct link API. Receive data via the program port ``port`` and write to a file named ``outfile``. :param port: Program port from which data will be received. Can be specified by a numerical port ID or by name. :type port: ``Union[PortId, str]`` :param outfile: Name of file to which received output is written. :type outfile: ``str``. :Keyword Arguments: * **nonblock** (``bool``) -- Nonblocking if ``True``, blocking otherwise. :returns: Handle to the task launched by :py:meth:`SdkRuntime.receive_tofile`. :rtype: :py:class:`Task` .. py:method:: report_port_infos() :module: cerebras.sdk.runtime.sdkruntimepybind Part of the :py:class:`SdkRuntime` direct link API. Reports the port name, color and absolute coordinate of every program data port. .. py:method:: run() :module: cerebras.sdk.runtime.sdkruntimepybind Start the simfabric or WSE run and wait for commands from the host runtime. .. py:method:: send(port: Union[PortId, str], src: numpy.ndarray, n_wavelets: int, **kwargs) -> Task :module: cerebras.sdk.runtime.sdkruntimepybind Part of the :py:class:`SdkRuntime` direct link API. Stream ``n_wavelets`` wavelets from ``src`` to the device via the port ``port``. :param port: Target program port in which to stream data. Can be specified by a numerical port ID or by name. :type port: ``Union[PortId, str]`` :param src: Input source array whose contents will be streamed to the device. :type src: ``numpy.ndarray``. :param n_wavelets: Number of wavelets to send. :type n_wavelets: ``int`` :Keyword Arguments: * **nonblock** (``bool``) -- Nonblocking if ``True``, blocking otherwise. :returns: Handle to the task launched by :py:meth:`SdkRuntime.send`. :rtype: :py:class:`Task` .. py:method:: send(port: Union[PortId, str], src: numpy.ndarray, **kwargs) -> Task :module: cerebras.sdk.runtime.sdkruntimepybind :noindex: Part of the :py:class:`SdkRuntime` direct link API. Same as above when ``src.dtype`` is exactly ``np.int32``, ``np.uint32`` or ``np.float32``. In that case, the runtime infers ``n_wavelets`` from ``len(src)``. .. py:method:: stop() :module: cerebras.sdk.runtime.sdkruntimepybind Wait for all pending commands (data transfers and kernel function calls) to complete and then stop simfabric or WSE. After this call is complete, no new commands will be accepted for this :py:class:`SdkRuntime` object. :py:meth:`SdkRuntime.stop` must be called to end a program. Otherwise, the runtime will emit an error. .. py:method:: task_wait(task_handle: Task) :module: cerebras.sdk.runtime.sdkruntimepybind Wait for the task ``task_handle`` to complete. :param task_handle: Handle to a task previously launched by :py:class:`SdkRuntime`. :type task_handle: :py:class:`Task` SdkTarget ^^^^^^^^^ .. py:class:: SdkTarget :module: cerebras.sdk.runtime.sdkruntimepybind Bases: :class:`Enum` Specifies a target compilation architecture. :Values: * **WSE2** * **WSE3** SimfabConfig ^^^^^^^^^^^^ .. py:class:: SimfabConfig(num_threads: int = 16, suppress_trace: bool = False, dump_core: bool = False, core_path: Optional[Union[pathlib.Path, str]] = None) :module: cerebras.sdk.runtime.sdkruntimepybind Bases: :class:`object` Specifies simfab configuration for simulator runs. :param num_threads: Number of CPU threads used by the simulator. Maximum is 64. :type num_threads: ``int`` :param suppress_trace: If ``True``, suppresses generation of ``simfab_traces`` when running. :type suppress_trace: ``bool`` :param dump_core: If ``True``, produces a coredump after execution ends. :type dump_core: ``bool`` :param core_path: Name of produced coredump. ``None`` (default) is ``out.core``. :type core_path: ``Union[pathlib.Path, str, None]`` Task ^^^^ .. py:class:: Task :module: cerebras.sdk.runtime.sdkruntimepybind Handle to a task launched by :py:class:`SdkRuntime`. get_platform ^^^^^^^^^^^^ .. py:function:: get_platform(cmaddr: Optional[str] = None, config: SimfabConfig = SimfabConfig(), target: SdkTarget = SdkTarget::WSE3) -> SdkExecutionPlatform :module: cerebras.sdk.runtime.sdkruntimepybind Constructs an :py:class:`SdkExecutionPlatform` object configured by simulator or system settings and target architecture. :param cmaddr: CM address in ``"IP_ADDRESS:PORT"`` format. ``None`` (default) or the empty string chooses the simulator. :type cmaddr: ``Union[str, None]`` :param config: Simulator configuration object. Ignored when ``cmaddr`` is provided. :type config: :py:class:`SimfabConfig` :param target: Target architecture for the simulator or system. :type target: :py:class:`SdkTarget` :returns: A configured execution platform object. :rtype: :py:class:`SdkExecutionPlatform` get_simulator ^^^^^^^^^^^^^ .. py:function:: get_simulator(config: SimfabConfig = SimfabConfig(), target: SdkTarget = SdkTarget::WSE3) -> SdkExecutionPlatform :module: cerebras.sdk.runtime.sdkruntimepybind Constructs an :py:class:`SdkExecutionPlatform` object for simulator. :param config: Simulator configuration object. :type config: :py:class:`SimfabConfig` :param target: Target architecture for the simulator. :type target: :py:class:`SdkTarget` :returns: A configured execution platform object. :rtype: :py:class:`SdkExecutionPlatform` get_system ^^^^^^^^^^ .. py:function:: get_system(cmaddr: str) -> SdkExecutionPlatform :module: cerebras.sdk.runtime.sdkruntimepybind Constructs an :py:class:`SdkExecutionPlatform` object for a real system. :param cmaddr: CM address in ``"IP_ADDRESS:PORT"`` format. :type cmaddr: ``str`` :param config: Simulator configuration object. :type config: :py:class:`SimfabConfig` :param target: Target architecture for the simulator. :type target: :py:class:`SdkTarget` :returns: A configured execution platform object. :rtype: :py:class:`SdkExecutionPlatform` .. _sdkruntime-sdk-utils: sdk_utils module ---------------- Utility functions for common operations with ``SdkRuntime``. Import from ``cerebras.sdk.sdk_utils``. .. py:module:: cerebras.sdk.sdk_utils calculate_cycles ^^^^^^^^^^^^^^^^ .. py:function:: calculate_cycles(timestamp_buf: numpy.ndarray) -> numpy.int64: :module: cerebras.sdk.sdk_utils Converts values in ``timestamp_buf`` returned from device into a human-readable elapsed cycle count. :param timestamp_buf: array returned from device containing elapsed timestamp data :type timestamp_buf: ``numpy.ndarray`` :returns: Elapsed cycle count. :rtype: ``numpy.int64`` **Example**: Consider the following CSL snippet which records timestamps and produces a single array to copy back to the host, to generate an elapsed cycle count: .. code-block:: csl // import time module and create timestamp buffers const timestamp = @import_module("