20.2.38. PMIx_Compute_distances
PMIx_Compute_distances, PMIx_Compute_distances_nb — Compute the
distances from a specified process location, or from a specified device, to
the local devices.
20.2.38.1. SYNOPSIS
#include <pmix.h>
pmix_status_t PMIx_Compute_distances(pmix_topology_t *topo,
pmix_cpuset_t *cpuset,
pmix_info_t info[], size_t ninfo,
pmix_device_distance_t *distances[],
size_t *ndist);
pmix_status_t PMIx_Compute_distances_nb(pmix_topology_t *topo,
pmix_cpuset_t *cpuset,
pmix_info_t info[], size_t ninfo,
pmix_device_dist_cbfunc_t cbfunc,
void *cbdata);
20.2.38.1.1. Python Syntax
from pmix import *
foo = PMIxClient()
# ... after a successful foo.init() ...
# load the local topology first
rc = foo.load_topology()
# the cpuset is a Python dictionary describing the process location
pycpus = {'source': "hwloc", 'cpus': [0, 1]}
# the directives is a list of Python ``pmix_info_t`` dictionaries
pydirs = [{'key': PMIX_DEVICE_TYPE,
'value': PMIX_DEVTYPE_NETWORK, 'val_type': PMIX_UINT64}]
rc, distances = foo.compute_distances(pycpus, pydirs)
# the non-blocking form returns as soon as the request has been accepted
# and reports the result by executing a callback on the PMIx progress
# thread. The callback is run if and only if the call returned
# PMIX_SUCCESS, and must not itself make a blocking PMIx call.
def distcb(status, distances, cbdata):
# distances is a list of dictionaries, each carrying uuid, osname,
# type, mindist and maxdist
print("distances:", foo.error_string(status), distances)
rc = foo.compute_distances_nb(pycpus, pydirs, distcb, "mycbdata")
20.2.38.2. INPUT PARAMETERS
topo: Pointer to apmix_topology_tdescribing the topology of the node where the process is located. ANULLvalue indicates that the topology of the local node is to be used. If the caller’s own topology has not yet been loaded, the library will attempt to load it (see PMIx_Load_topology(3)) or, failing that, relay the request to the local PMIx server.cpuset: Pointer to apmix_cpuset_tidentifying the location (the set of processing units to which the process is bound) from which distances are to be computed. ANULLvalue indicates that the caller’s own location is to be used; if it has not yet been determined, the library will attempt to obtain it or relay the request to the local PMIx server. Ignored, and may beNULL, when thePMIX_DEVICE_DIST_ORIGINdirective is given.info: Pointer to an array of pmix_info_t(5) structures describing the device type(s) or specific device(s) whose distance is to be computed (see DIRECTIVES). ANULLvalue (withninfoof zero) requests distances to all device types supported by the underlying topology description.ninfo: Number of elements in theinfoarray.
For PMIx_Compute_distances_nb(3):
cbfunc: Callback function of type pmix_device_dist_cbfunc_t to be invoked when the operation is complete.cbdata: Opaque data pointer to be passed tocbfuncwhen invoked.
20.2.38.3. OUTPUT PARAMETERS
For the blocking form PMIx_Compute_distances(3):
distances: On successful return,*distancespoints to a newly allocated array ofpmix_device_distance_tstructures containing the minimum and maximum distances from the specified process location to each of the requested devices. Each element reports theuuid,osname,type,mindist, andmaxdistof a device. The array is allocated by the library and ownership passes to the caller, who is responsible for releasing it (for example, withPMIx_Device_distance_free()).ndist: On successful return,*ndistholds the number of elements in the returneddistancesarray.
On entry, the blocking form initializes *distances to NULL and *ndist
to zero.
For the non-blocking form, the array of pmix_device_distance_t and its count
are delivered as the dist and ndist arguments of the callback function.
The data provided to the callback is owned by the library; the callback is passed
a release_fn (and release_cbdata) that must be invoked when the caller is
finished with the dist array.
20.2.38.4. DESCRIPTION
Compute the distances between a process at a given location and the devices
available on a node. Both the minimum and maximum distance fields in each element
of the returned array are filled with the respective distances between the
process location and the device types (or specific devices) identified by the
info directives. In the absence of directives, distances to the network,
OpenFabrics, GPU and coprocessor devices on the node are returned.
Alternatively, distances can be computed from a device rather than from a
process location by naming that device with the PMIX_DEVICE_DIST_ORIGIN
directive — for example, to find the network devices nearest the GPU a
process is using. The cpuset plays no part in that case, so a process need
not be bound to ask. The origin device itself is included in the result, at a
distance of zero, if it is of a requested type.
Distances are relative, and smaller means closer. A distance from a process location is governed first by where the device attaches to the processor hierarchy (the package or NUMA domain it is local to); among devices that attach at the same place, a device fewer PCIe levels (bridges and switches) below that point is closer. A distance from a device follows the path between the two devices: devices under the same PCIe switch are closer than devices under the same host bridge, which are closer than devices on different host bridges of the same package, which are closer than devices on different packages. Because every device under a package is equally close to that package’s processors, only a distance measured from a device can distinguish the host bridges within a package.
PMIx_Compute_distances(3) is the blocking
form: it does not return until the computation completes, at which point the
result array is returned through the distances and ndist parameters.
PMIx_Compute_distances_nb(3) is the
non-blocking form: it returns immediately (PMIX_SUCCESS indicating that the
request was successfully initiated) and delivers the result later by invoking
cbfunc. As with all non-blocking PMIx operations, the caller must ensure that
the topo, cpuset, and info arguments remain valid until cbfunc
has been invoked.
If the local PMIx library can satisfy the request itself (i.e., it has access to a suitable topology and cpuset), it does so directly. Otherwise, a connected client or tool relays the request to its local PMIx server. A process acting solely as a server, or a process that is not connected to a server and cannot compute the distances locally, cannot service the request.
20.2.38.5. DIRECTIVES
The following attributes are optional for PMIx implementations and may be passed
in the info array to select the devices whose distances are to be computed:
PMIX_DEVICE_DISTANCES("pmix.dev.dist") — request the return of an array ofpmix_device_distance_tdescribing the distances to devices on the local node.PMIX_DEVICE_TYPE("pmix.dev.type") — apmix_device_type_tbitmask specifying the type(s) of device whose distances are to be computed. Values includePMIX_DEVTYPE_BLOCK,PMIX_DEVTYPE_GPU,PMIX_DEVTYPE_NETWORK,PMIX_DEVTYPE_OPENFABRICS,PMIX_DEVTYPE_DMA,PMIX_DEVTYPE_COPROC, and others defined inpmix_common.h.PMIX_DEVICE_ID("pmix.dev.id") — a system-wide UUID or node-local OS name (char*) identifying a particular device. A device may also be named by its vendor identity (e.g., an NVIDIAGPU-UUID) or its PCI bus id ("0000:06:00.0"). The attribute may be given more than once to request distances to several devices.PMIX_DEVICE_DIST_ORIGIN("pmix.dev.dist.origin") — achar*naming the device from which distances are to be computed, in any of the forms accepted byPMIX_DEVICE_ID, in place of a process location. Thecpusetargument is ignored when this directive is given. ReturnsPMIX_ERR_NOT_FOUNDif no device answers to the name, andPMIX_ERR_BAD_PARAMif more than one does.
20.2.38.6. RETURN VALUE
Returns PMIX_SUCCESS on success. On error, a negative value corresponding to
a PMIx error constant is returned, including:
PMIX_ERR_INIT— the PMIx library has not been initialized.PMIX_ERR_NOT_AVAILABLE— the operation cannot be serviced because the library’s progress engine has been stopped.PMIX_ERR_UNREACH— the request could not be satisfied locally and the local PMIx server could not be reached (or the caller is a server, or is not connected to a server).PMIX_ERR_NOT_SUPPORTED—PMIX_DEVICE_DIST_ORIGINwas given, the request could not be satisfied locally, and the local PMIx server predates support for that directive.
For the blocking form, the value returned is the status of the completed
operation. For the non-blocking form, a return of PMIX_SUCCESS indicates only
that the request was successfully initiated; the final status of the operation is
reported as the status argument to cbfunc. Any other negative value
indicates an appropriate error condition. PMIx error constants are defined in
pmix_common.h.
20.2.38.7. NOTES
The PMIX_DEVICE_DIST_CREATE and PMIX_DEVICE_DIST_FREE convenience macros
are deprecated. New code should manage pmix_device_distance_t arrays using
the PMIx_Device_distance_create() and PMIx_Device_distance_free()
functions.
A process whose threads are not all bound to the same location may return
inconsistent results from calls to this API by different threads if the
PMIX_CPUBIND_THREAD binding envelope was used when generating the cpuset.
20.2.38.8. PROGRESS THREAD RESTRICTION
A blocking PMIx call must not be made from within the PMIx progress thread. Any code the library itself invokes runs on that thread: an event handler registered through PMIx_Register_event_handler(3), a callback passed to a non-blocking PMIx API, and — in a server or tool — the completion of a host-module up-call. A blocking call waits for work that the progress thread has to perform, so making one from that thread waits for itself and never returns. The PMIx Standard disallows it, and there is no way for an implementation to service such a request.
Where this call has a blocking form — including the blocking
behavior a non-blocking entry point adopts when it is passed a NULL
cbfunc — that form detects the situation and returns
PMIX_ERR_WOULD_BLOCK immediately, accompanied by a diagnostic naming
the call. Nothing is done and no callback is invoked.
PMIX_ERR_WOULD_BLOCK here is not a transient condition to retry: it
reports a call that cannot be serviced from where it was made. Reissue
it as the non-blocking form with a callback, or from a thread of your
own.