Charm

The object charm4py.charm exists on every process and represents the Charm4py runtime. It is available after importing charm4py. To start the application, you register your Chare classes and start the runtime by calling charm.start().

charm is also a chare, and some of its methods can be called remotely, via its thisProxy attribute.

The API of charm is described in this section.

Start and exit

  • charm.start(entry=None, classes=[], modules=[], interactive=False):

    Start the runtime system. This is required on all processes, and registers Chare classes with the runtime.

    entry is the user-defined entry point to start the application. The runtime transfers control to this entry point after it has initialized. entry can be a Python function or a chare type. If it is a chare type, the runtime will create an instance of this chare on PE 0, and transfer control to the chare’s constructor. The entry point function (or chare constructor) must have only one parameter, which is used to receive the application arguments.

    If interactive is True, an entry point is not needed and instead Charm4py will transfer control to an interactive prompt (Read-Eval-Print Loop) on PE 0.

    On calling charm.start(), Charm4py automatically registers any chare types that are defined in the __main__ module. If desired, a list of chare types can also be passed explicitly using the classes optional parameter. These must be the classes that are to be registered, and can be classes defined in other modules. The modules parameter can be used to automatically register any chare types defined inside the given list of modules. These modules are to be given by their names.

    Note

    If charm4py is imported and the program exits without calling charm.start(), a warning will be printed. This is to remind users in case they forget to start the runtime (otherwise the program might hang or exit without any output).

  • charm.exit(exit_code=0):

    Exits the parallel program, shutting down all processes. Can be called from any chare or process after the runtime has started. The exit_code will be received by the OS on exit.

    This method can be called remotely. For this reason, it can also be used a callback (of reductions, etc). For example: self.reduce(charm.thisProxy.exit).

    Note

    Calling Python’s exit() function from a chare has the same effect (Charm4py intercepts the SystemExit exception and calls charm.exit().

  • charm.abort(message):

    Aborts the program, printing the specified message and a stack trace of the PE which aborted. It can be called from any chare or process after the runtime has started.

Broadcasting globals

  • charm.updateGlobals(globals_dict, module_name=’__main__’):

    Update the globals dictionary of module module_name with the key/value pairs from globals_dict, overwriting existing keys.

    This can only be called as a remote method.

    Example:

    # broadcast global 'X' to all processes, wait for completion
    charm.thisProxy.updateGlobals({'X': 333}, awaitable=True).get()
    

Query processor and host information

  • charm.myPe():

    Returns the PE number on which the caller is currently running.

    Note

    Some chares can migrate between PEs during execution. As such, the value returned by myPe() can vary for these chares.

  • charm.numPes():

    Returns the total number of PEs that the application is running on.

  • charm.myHost():

    Returns the host number on which the caller is running.

  • charm.numHosts():

    Returns the total number of hosts on which the application is running on.

  • charm.getHostPes(host):

    Return the list of PEs on the specified host (given by host number).

  • charm.getHostFirstPe(host):

    Return the first PE on the specified host (given by host number).

  • charm.getHostNumPes(host):

    Return the number of PEs on the specified host (given by host number).

  • charm.getPeHost(pe):

    Return the host number on which pe resides.

  • charm.getPeHostRank(pe):

    Returns the local rank number of pe on the host on which it resides.

Waiting for events and completion

You can obtain Futures when calling remote methods, to wait for completion (see Proxies).

charm has the following methods related to waiting for events:

  • charm.awaitCreation(*proxies):

    Suspends the current coroutine until all of the chares in the collections referenced by the given proxies have been created on the system (in other words, until their constructors have been called).

    Note

    The coroutine must have triggered the creation of the collections.

  • charm.wait(awaitables):

    Suspends the current coroutine until the objects in awaitables become ready. The objects supported are Futures and Channels.

  • charm.iwait(awaitables):

    Iteratively yield objects from awaitables as they become ready. The objects supported are Futures and Channels. This can only be called from coroutines.

    Warning

    Do not suspend the coroutine until iawait has finished yielding all the objects.

  • charm.startQD(callback)

    Start Quiescence Detection (QD). Quiescence is defined as the state in which no PE is executing a remote method, no messages are awaiting processing, and there are no messages in flight. When QD is reached, the runtime will call the callback. The callback must be a Future or the remote method of a chare(s) (specified by proxy.method, where proxy can be any type of proxy, including a proxy to a single element or a whole collection).

  • charm.waitQD()

    Suspend the current coroutine until Quiescence Detection is reached.

Timer-based scheduling

  • charm.sleep(secs)

    If this is called from a coroutine, it suspends the coroutine until at least secs seconds have elapsed (the process is free to do other work in that time). If it is not called from a coroutine, it is equivalent to doing time.sleep(secs) which puts the process to sleep.

  • charm.scheduleCallableAfter(callable_obj, secs, args=[])

    Schedule callable_obj to be called after secs seconds. The callable can be any Python callable, as well as Futures and the remote method of a chare(s) (specified by proxy.method, where proxy can be any type of proxy, including a proxy to a single element or a whole collection). A list of arguments can be passed via args (the callable will be called with these arguments). Note that this method only guarantees that the callable is called after secs seconds, but the exact time depends on the work the PE is doing.

Sections

Remote code execution

Note

These are disabled by default. Set charm.options.remote_exec to True to enable.

  • charm.exec(code, module_name=’__main__’):

    Calls Python’s exec(code) on this PE using the specified module as globals. code is a string containing Python code.

    This can only be called as a remote method.

  • charm.eval(expression, module_name=’__main__’):

    Calls Python’s eval(expression) on this PE using the specified module as globals.

    This can only be called as a remote method.

Profiling

  • charm.printStats():

    Print profiling metrics and statistics. Profiling must have been enabled by setting charm.options.profiling to True before calling charm.start(). See Profiling for more information.

    This can be called as a remote method.

    Example:

    # print stats of PE 2 and wait for completion
    charm.thisProxy[2].printStats(awaitable=True).get()
    

charm.options

You can set runtime options via the charm.options object, which has the following attributes:

  • local_msg_optim (default=True): if True, remote method arguments sent to a chare that is in the same PE as the caller will be passed by reference (instead of copied or serialized). Best performance is obtained when this is enabled.
  • local_msg_buf_size (default=50): size of the pool used to store “local” messages (see previous option).
  • pickle_protocol (default=-1): determines the pickle protocol used by Charm4py. A value of -1 tells pickle to use the highest protocol number (recommended). Note that not every type of argument sent to a remote method is pickled (see Serialization).
  • profiling (default=False): if True, Charm4py will profile the program and collect timing and message statistics. See Profiling for more information. Note that this will affect performance of the application.
  • quiet (default=False): suppresses the initial Charm++ and Charm4py output.
  • remote_exec (default=False): if True, allows remote calling of charm.exec() and charm.eval().