Skip to content

← utilities package

WithCoreLimit

Run the given computational graph with a limit on the number of cores that can be used by the process.

This can be used to prevent churn due to math backends that would otherwise use excessively many threads / cores, and can also help control the total number of cores used when multiple processes are involved, by allotting each process a subset of the total number of cores. The graph has a dummy input named "with", which is used to tag the start of the graph that is running under control of this node, which is all nodes downstream of the Placeholder that accepts the "with" input, up to but excluding the WithCoreLimit node itself. However, note that this only applies to a certain set of math libraries, including BLAS, OpenMP, and libraries using them. Also note that, if your computation involves multi-process parallelism (such as when using a Parallel ForEach loop with any multiprocess backend except for 'serial' or the rarely-used 'threading' backend), then this setting has no effect on what happens in those sub-processes, which would need their own WithCoreLimit node to limit their use of cores. Version 0.9.0

Ports/Properties

graph

Computation to run.

  • verbose name: Graph
  • default value: None
  • port type: GraphPort
  • value type: Graph

graph__signature

Optionally the slotname of a Placeholder node that shall mark the starting point of the graph that runs under the with context. As with all "With" context manager nodes in NeuroPype, the graph that runs under the context managed by this node is preceding the context manager node in the graph, rather than following it. This is accomplished by wiring the final node of the graph that shall execute under the governance of the context manager into the "graph" input port of the subsequent "With" node. In graphical UIs, this edge will be drawn in dotted style to indicate that this is not normal forward data flow where first the preceding node executes and then the subsequent node receives its output, but that instead the subsequent node (the context manager) receives a portion of the preceding graph, which it then runs in such a way that the context applies. You can use a "tilde" binding, spelled as (~), which affects the same nodes that a then or else branch in an IfElse node would control, which is normally what one would expect. However, note that this can have sometimes the unexpected consequence that simply wiring a value into your graph may "infect" an upstream portion of the graph with unintentionally running under the context, too. As an alternative, you can instead rely on a named Placeholder node to mark the beginning of the managed graph. The typical way to do this is to list a single placeholder name, e.g., (with), and then to create a Placeholder in your graph whose slotname is set to "with". Then, only the nodes that are downstream of (i.e., formally depending on) that placeholder will run under the context defined by the "With" node. In this case you need to make everything that shall be part of the context dependent on the placeholder, which can be accomplished by wiring the update output port of the Placeholder into the update input port of any nodes that shall run under the context (this dependency propagates down the graph, so you don't need to wire it to every node, just to the first node(s) that you want to be part of the context). Any computation in this graph will then use at most this many cores, but note that this does not apply to any sub-processes that may be spawned by the computation (e.g., when using a Parallel ForEach loop with a multiprocess backend). The WithCoreLimit node can also be nested, such that the managed graph itself may contain other WithCoreLimit nodes and their associated "with" Placeholders (these nested placeholders are distinguished by being wired (indirectly) into the "graph" port of the nested WithCoreLimit node, while the outer "with" Placeholder should only be wired into the update port of the nested WithCoreLimit, but you can also rename the tag name to something other than 'with' to avoid ambiguity).

  • verbose name: Graph [Tag]
  • default value: (with)
  • port type: Port
  • value type: object (can be None)

result

Result of the computation.

  • verbose name: Result
  • default value: None
  • port type: DataPort
  • value type: object (can be None)
  • data direction: OUT

num_cores

Maximum number of cores available to the computation. This can also override a limit imposed by an outer caller context. If set to -1, the computation will be able to use as many cores as there are on the system. If set to a positive integer, then the computation will be limited to use this many threads / cores. If left unspecified (None/use default), then this node does nothing.

  • verbose name: Number Of Cores
  • default value: -1
  • port type: IntPort
  • value type: int (can be None)

is_global

If True, the context implicitly applies to the entire graph (except for those parts that are configuring the context itself). In this case the node must not have anything wired into its graph input and must not have any successors.

  • verbose name: Is Global
  • default value: False
  • port type: BoolPort
  • value type: bool (can be None)

set_breakpoint

Set a breakpoint on this node. If this is enabled, your debugger (if one is attached) will trigger a breakpoint.

  • verbose name: Set Breakpoint (Debug Only)
  • default value: False
  • port type: BoolPort
  • value type: bool (can be None)

metadata

User-definable meta-data associated with the node. Usually reserved for technical purposes.

  • verbose name: Metadata
  • default value: {}
  • port type: DictPort
  • value type: dict (can be None)