Util#

group util

Defines

LEGATE_CONCAT_(x, ...)#

Concatenate a series of tokens without macro expansion.

This macro will NOT macro-expand any tokens passed to it. If this behavior is undesirable, and the user wishes to have all tokens expanded before concatenation, use LEGATE_CONCAT() instead. For example:

#define FOO 1
#define BAR 2

LEGATE_CONCAT(FOO, BAR) // expands to FOOBAR

See also

LEGATE_CONCAT()

Parameters:
  • x – The first parameter to concatenate.

  • ... – The remaining parameters to concatenate.

LEGATE_CONCAT(x, ...)#

Concatenate a series of tokens.

This macro will first macro-expand any tokens passed to it. If this behavior is undesirable, use LEGATE_CONCAT_() instead. For example:

#define FOO 1
#define BAR 2

LEGATE_CONCAT(FOO, BAR) // expands to 12

See also

LEGATE_CONCAT_()

Parameters:
  • x – The first parameter to concatenate.

  • ... – The remaining parameters to concatenate.

LEGATE_STRINGIZE_(...)#

Stringize a series of tokens.

This macro will turn its arguments into compile-time constant C strings.

This macro will NOT macro-expand any tokens passed to it. If this behavior is undesirable, and the user wishes to have all tokens expanded before stringification, use LEGATE_STRINGIZE() instead. For example:

#define FOO 1
#define BAR 2

LEGATE_STRINGIZE_(FOO, BAR) // expands to "FOO, BAR" (note the "")

Parameters:
  • ... – The tokens to stringize.

LEGATE_STRINGIZE(...)#

Stringize a series of tokens.

This macro will turn its arguments into compile-time constant C strings.

This macro will first macro-expand any tokens passed to it. If this behavior is undesirable, use LEGATE_STRINGIZE_() instead. For example:

#define FOO 1
#define BAR 2

LEGATE_STRINGIZE(FOO, BAR) // expands to "1, 2" (note the "")

Parameters:
  • ... – The tokens to stringize.

LEGATE_DEFINED(x)#

Determine if a preprocessor definition is positively defined.

LEGATE_DEFINED() returns 1 if and only if x expands to integer literal 1, or is defined (but empty). In all other cases, LEGATE_DEFINED() returns the integer literal 0. Therefore this macro should not be used if its argument may expand to a non-empty value other than

  1. The only exception is if the argument is defined but expands to 0, in which case LEGATE_DEFINED() will also expand to 0:

#define FOO_EMPTY
#define FOO_ONE 1
#define FOO_ZERO 0
// #define FOO_UNDEFINED

static_assert(LEGATE_DEFINED(FOO_EMPTY) == 1);
static_assert(LEGATE_DEFINED(FOO_ONE) == 1);
static_assert(LEGATE_DEFINED(FOO_ZERO) == 0);
static_assert(LEGATE_DEFINED(FOO_UNDEFINED) == 0);

Conceptually, LEGATE_DEFINED() is equivalent to

#if defined(x) && (x == 1 || x == *empty*)
// "return" 1
#else
// "return" 0
#endif

As a result this macro works both in preprocessor statements:

#if LEGATE_DEFINED(FOO_BAR)
  foo_bar_is_defined();
#else
  foo_bar_is_not_defined();
#endif

And in regular C++ code:

if (LEGATE_DEFINED(FOO_BAR)) {
  foo_bar_is_defined();
} else {
  foo_bar_is_not_defined();
}

Note that in the C++ example above both arms of the if statement must compile. If this is not desired, then — since LEGATE_DEFINED() produces a compile-time constant expression — the user may use C++17’s if constexpr to block out one of the arms:

if constexpr (LEGATE_DEFINED(FOO_BAR)) {
  foo_bar_is_defined();
} else {
  foo_bar_is_not_defined();
}

See also

LEGATE_CONCAT()

Parameters:
  • x – The legate preprocessor definition.

Returns:

1 if the argument is defined and true, 0 otherwise.

LEGATE_SCOPE_GUARD(...)#

Construct an unnamed legate::ScopeGuard from the contents of the macro arguments.

It is impossible to enable or disable the legate::ScopeGuard constructed by this macro.

This macro is useful if the user need only define some action to be executed on scope exit, but doesn’t care to name the legate::ScopeGuard and/or has no need to enable/disable it after construction.

For example:

int *mem = std::malloc(10 * sizeof(int));

LEGATE_SCOPE_GUARD(std::free(mem));
// use mem...
// scope exits, and mem is free'd.

Multi-line statements are also supported:

int *mem = std::malloc(10 * sizeof(int));

LEGATE_SCOPE_GUARD(
  if (frobnicate()) {
    std::free(mem);
  }
);
// use mem...
// scope exits, and mem is free'd depending on return value of frobnicate()

If the body of the guard should only be executed on failure, use LEGATE_SCOPE_FAIL instead.

See also

ScopeGuard

Parameters:
LEGATE_SCOPE_FAIL(...)#

Construct an unnamed legate::ScopeFail from the contents of the macro arguments.

This macro behaves identically to LEGATE_SCOPE_GUARD, except that it creates a legate::ScopeFail instead of a legate::ScopeGuard. Please refer to its documentation for further discussion.

See also

ScopeFail

Parameters:

Typedefs

template<Type::Code CODE>
using type_of_t = typename type_of_detail::type_of<CODE>::type#

A template that converts type codes to types.

Functions

template<typename T, int DIM>
std::string print_dense_array(const T *base, const Point<DIM> &extents, std::size_t strides[DIM])#

Converts the dense array into a string.

Parameters:
  • base – Array to convert

  • extents – Extents of the array

  • strides – Strides for dimensions

Returns:

A string expressing the contents of the array

template<int DIM, typename ACC>
std::string print_dense_array(ACC accessor, const Rect<DIM> &rect)#

Converts the dense array into a string using an accessor.

Parameters:
  • accessor – Accessor to an array

  • rect – Sub-rectangle within which the elements should be retrieved

Returns:

A string expressing the contents of the array

template<typename Functor, typename ...Fnargs>
constexpr decltype(auto) double_dispatch(int dim, Type::Code code, Functor f, Fnargs&&... args)#

Converts the runtime dimension and type code into compile time constants and invokes the functor with them.

The functor’s operator() should take a dimension and a type code as template parameters.

Parameters:
  • dim – Dimension

  • codeType code

  • f – Functor to dispatch

  • args – Extra arguments to the functor

Returns:

The functor’s return value

template<typename Functor, typename ...Fnargs>
constexpr decltype(auto) double_dispatch(int dim1, int dim2, Functor f, Fnargs&&... args)#

Converts the runtime dimensions into compile time constants and invokes the functor with them.

The functor’s operator() should take exactly two integers as template parameters.

Parameters:
  • dim1 – First dimension

  • dim2 – Second dimension

  • f – Functor to dispatch

  • args – Extra arguments to the functor

Returns:

The functor’s return value

template<typename Functor, typename ...Fnargs>
constexpr decltype(auto) dim_dispatch(int dim, Functor f, Fnargs&&... args)#

Converts the runtime dimension into a compile time constant and invokes the functor with it.

The functor’s operator() should take an integer as its sole template parameter.

Parameters:
  • dim – Dimension

  • f – Functor to dispatch

  • args – Extra arguments to the functor

Returns:

The functor’s return value

template<typename Functor, typename ...Fnargs>
constexpr decltype(auto) type_dispatch(Type::Code code, Functor &&f, Fnargs&&... args)#

Converts the runtime type code into a compile time constant and invokes the functor with it.

The functor’s operator() should take a type code as its sole template parameter.

Parameters:
  • codeType code

  • f – Functor to dispatch

  • args – Extra arguments to the functor

Returns:

The functor’s return value

template<typename F>
ScopeGuard<F> make_scope_guard(F &&fn) noexcept#

Create a ScopeGuard from a given functor.

See also

ScopeGuard

Parameters:

fn – The functor to create the ScopeGuard with.

Template Parameters:

The – type of fn, usually inferred from the argument itself.

Returns:

The constructed ScopeGuard

template<typename F>
ScopeFail<F> make_scope_fail(F &&fn) noexcept#

Create a ScopeFail from a given functor.

See also

ScopeFail

Parameters:

fn – The functor to create the ScopeFail with.

Template Parameters:

The – type of fn, usually inferred from the argument itself.

Returns:

The constructed ScopeFail

Time measure_microseconds()#

Returns a timestamp at the resolution of microseconds.

The returned timestamp indicates the time at which all preceding Legate operations finish. This timestamp generation is a non-blocking operation, and the blocking happens when the value wrapped within the returned Time object is retrieved.

Returns:

A Time object

Time measure_nanoseconds()#

Returns a timestamp at the resolution of nanoseconds.

The returned timestamp indicates the time at which all preceding Legate operations finish. This timestamp generation is a non-blocking operation, and the blocking happens when the value wrapped within the returned Time object is retrieved.

Returns:

A Time object

Variables

template<typename T>
constexpr Type::Code type_code_of_v = type_code_of_detail::type_code_of<T>::value#

A template constexpr that converts types to type codes.

class Scope#
#include <core/runtime/scope.h>

A helper class to configure task execution.

The Scope class offers APIs to configure runtime parameters for task execution. The parameters set by a Scope object are effective only for the lifetime of the object. Currently, Scope can be used to configure the following parameters:

1) Task priority: Each task is associated with a priority value. The higher the value, the earlier among a set of ready-to-run tasks the task will get scheduled for execution. (the task with a higher priority, however, does not preempt another with a lower priority that is already running on the processor.) Task priorities are a signed 32-bit integer value. By default, all tasks get assigned to 0 for the priorities.

2) Provenance: User programs or libraries often want to attach provenance information to each of their operations and have it rendered in profiling outputs. Such information can be passed as a string via a Scope object, which then will be attached to all operations issued within the Scope’s lifetime.

3) Machine: By default, Legate operations target the entire machine available for the program. When a user program wants to assign a subset of the machine to its operations, it can subdivide the machine using the machine API (see Machine for details) and set a sub-machine for the scope using Scope. All operations within the lifetime of the Scope object can use only the sub-machine for their execution.

Each parameter can be set only once via each Scope object. Multiple attempts to set the same parameter would raise an exception.

Public Functions

Scope()#

Constructs an empty Scope object.

explicit Scope(std::int32_t priority)#

Constructs a Scope with a given task priority.

Equivalent to

auto scope = Scope();
scope.set_priority(priority);

Parameters:

priority – Task priority to set to the scope

explicit Scope(ExceptionMode exception_mode)#

Constructs a Scope with a given exception mode.

Equivalent to

auto scope = Scope();
scope.set_exception_mode(exception_mode);

Parameters:

exception_mode – Exception mode to set to the scope

explicit Scope(std::string provenance)#

Constructs a Scope with a given provenance string.

Equivalent to

auto scope = Scope();
scope.set_provenance(provenance);

Parameters:

provenance – Provenance string to set to the scope

explicit Scope(const mapping::Machine &machine)#

Constructs a Scope with a given machine.

Equivalent to

auto scope = Scope();
scope.set_machine(machine);

The given machine is intersected with the machine from the outer scope

See also

set_machine

Parameters:

machine – Machine to use within the scope

Throws:

std::runtime_error – If the intersected machine is empty

Scope &&with_priority(std::int32_t priority) &&#

Sets a given task priority to the scope.

Parameters:

priority – Task priority to set to the scope

Throws:

std::invalid_argument – If a task priority has already been set via this Scope object

Scope &&with_exception_mode(ExceptionMode exception_mode) &&#

Sets a given exception mode to the scope.

Parameters:

exception_mode – Exception mode to set to the scope

Throws:

std::invalid_argument – If an exception mode has already been set via this Scope object

Scope &&with_provenance(std::string provenance) &&#

Sets a given provenance string to the scope.

Parameters:

provenance – Provenance string to set to the scope

Throws:

std::invalid_argument – If a provenance string has already been set via this Scope object

Scope &&with_machine(const mapping::Machine &machine) &&#

Sets a given machine to the scope.

The given machine is intersected with the machine from the outer scope

See also

set_machine

Parameters:

machine – Machine to use within the scope

Throws:
  • std::runtime_error – If the intersected machine is empty

  • std::invalid_argument – If a machine has already been set via this Scope object

void set_priority(std::int32_t priority)#

Sets a given task priority to the scope.

Parameters:

priority – Task priority to set to the scope

Throws:

std::invalid_argument – If a task priority has already been set via this Scope object

void set_exception_mode(ExceptionMode exception_mode)#

Sets a given exception mode to the scope.

Parameters:

exception_mode – Exception mode to set to the scope

Throws:

std::invalid_argument – If an exception mode has already been set via this Scope object

void set_provenance(std::string provenance)#

Sets a given provenance string to the scope.

Parameters:

provenance – Provenance string to set to the scope

Throws:

std::invalid_argument – If a provenance string has already been set via this Scope object

void set_machine(const mapping::Machine &machine)#

Sets a given machine to the scope.

The given machine is intersected with the machine from the outer scope, so the actual machine used in this scope will always be a subset of the outer scope’s.

For example, if the machine of the current scope has GPUs 2, 3, 4, and 5, and a new scope is created with another machine with GPUs 3, 4, 5, and 6, then only the GPUs 3, 4, and 5 will be set to the new scope.

Parameters:

machine – Machine to use within the scope

Throws:
  • std::runtime_error – If the intersected machine is empty

  • std::invalid_argument – If a machine has already been set via this Scope object

Public Static Functions

static std::int32_t priority()#

Returns the task priority of the current scope.

return Current task priority

static legate::ExceptionMode exception_mode()#

Returns the exception mode of the current scope.

return Current exception mode

static std::string_view provenance()#

Returns the provenance string of the current scope.

Returns:

Current provenance string

static mapping::Machine machine()#

Returns the machine of the current scope.

Returns:

Current machine

class Impl#
template<Type::Code CODE>
struct is_integral : public std::is_integral<type_of_t<CODE>>#
#include <core/type/type_traits.h>

A predicate that holds if the type code is of an integral type.

template<Type::Code CODE>
struct is_signed : public std::is_signed<type_of_t<CODE>>#
#include <core/type/type_traits.h>

A predicate that holds if the type code is of a signed integral type.

template<Type::Code CODE>
struct is_unsigned : public std::is_unsigned<type_of_t<CODE>>#
#include <core/type/type_traits.h>

A predicate that holds if the type code is of an unsigned integral type.

template<Type::Code CODE>
struct is_floating_point : public std::is_floating_point<type_of_t<CODE>>#
#include <core/type/type_traits.h>

A predicate that holds if the type code is of a floating point type.

template<Type::Code CODE>
struct is_complex : public std::false_type#
#include <core/type/type_traits.h>

A predicate that holds if the type code is of a complex type.

template<typename T>
struct is_complex_type : public std::false_type#
#include <core/type/type_traits.h>

A predicate that holds if the type is one of the supported complex types.

template<typename F>
class ScopeGuard#
#include <core/utilities/scope_guard.h>

A simple wrapper around a callable that automatically executes the callable on exiting the scope.

Template Parameters:

F – The type of the callable to execute.

Public Types

using value_type = F#

The type of callable stored within the ScopeGuard.

Public Functions

explicit ScopeGuard(value_type &&fn, bool enabled = true) noexcept#

Construct a ScopeGuard.

On destruction, a ScopeGuard will execute fn if and only if it is in the enabled state. fn will be invoked with no arguments, and any return value discarded. fn must be no-throw move-constructible, and must not throw any exceptions when invoked.

See also

ScopeFail

Parameters:
  • fn – The function to execute.

  • enabled – Whether the ScopeGuard should start in the “enabled” state.

ScopeGuard(ScopeGuard &&other) noexcept#

Move-construct a ScopeGuard.

other will be left in the “disabled” state, and will not execute its held functor upon destruction. Furthermore, the held functor is moved into the receiving ScopeGuard, so other's functor may be in an indeterminate state. It is therefore not advised to re-enable other.

Parameters:

other – The ScopeGuard to move from.

ScopeGuard &operator=(ScopeGuard &&other) noexcept#

Construct a ScopeGuard via move-assignment.

This routine has no effect if other and this are the same.

other will be left in the “disabled” state, and will not execute its held functor upon destruction. Furthermore, the held functor is moved into the receiving ScopeGuard, so other's functor may be in an indeterminate state. It is therefore not advised to re-enable other.

Parameters:

other – The ScopeGuard to move from.

Returns:

A reference to this.

~ScopeGuard() noexcept#

Destroy a ScopeGuard.

If the ScopeGuard is currently in the enabled state, executes the held functor, otherwise does nothing.

bool enabled() const#

Query a ScopeGuard’s state.

Returns:

true if the ScopeGuard is enabled, false otherwise.

void disable()#

Disable a ScopeGuard.

This routine prevents a ScopeGuard from executing its held functor on destruction. On return, ScopeGuard::enabled() will return false.

Calling this routine on an already disabled ScopeGuard has no effect.

void enable()#

Enable a ScopeGuard.

This routine makes a ScopeGuard execute its held functor on destruction. On return, ScopeGuard::enabled() will return true.

Calling this routine on an already enabled ScopeGuard has no effect.

template<typename F>
class ScopeFail#
#include <core/utilities/scope_guard.h>

Similar to ScopeGuard, except that the callable is only executed if the scope is exited due to an exception.

Template Parameters:

F – The type of the callable to execute.

Public Types

using value_type = F#

The type of callable stored within the ScopeFail.

Public Functions

explicit ScopeFail(value_type &&fn) noexcept#

Construct a ScopeFail.

On destruction, a ScopeFail will execute fn if and only if the scope is being exited due to an uncaught exception. Therefore, unlike ScopeGuard, it is not possible to “disable” a ScopeFail.

fn will be invoked with no arguments, and any return value discarded. fn must be no-throw move-constructible, and must not throw any exceptions when invoked.

See also

ScopeGuard

Parameters:

fn – The function to execute.

~ScopeFail() noexcept#

Destroy a ScopeFail.

If the ScopeFail is being destroyed due to the result of exception-related stack unwinding, then the held functor is executed, otherwise has no effect.

class Time#
#include <timing/timing.h>

Deferred timestamp class.

Public Functions

std::int64_t value() const#

Returns the timestamp value in this Time object.

Blocks on all Legate operations preceding the call that generated this Time object.

Returns:

A timestamp value

class Impl#