PXL
pxl Namespace Reference

Namespaces

 detail
 

Classes

class  Context
 An execution abstraction of a Device object. More...
 
class  NDArray
 NDArray is a class that can be used in both host and device code. NDArray is automatically divided into multiple NDArray slices for each task. More...
 
struct  ArgDirections
 
class  Function
 Defines a function to be executed by each thread on the MU. More...
 
class  Job
 Manages device compute resources and offloads user applications. More...
 
struct  LaunchResult
 
class  LaunchBuilder
 Configurable kernel execution request. More...
 
class  Launcher
 Execution context for kernel launches on XCENA devices. More...
 
class  Map
 The Map class represents a map operation in the XCENA execution framework. More...
 
struct  KernelTraits
 Traits class that maps a kernel function pointer to its name string. More...
 
class  Module
 A container for Function of MU kernel binary. More...
 
class  ScopedProfile
 
class  StageBuilder
 Builds a chain of kernel stages for sequential/parallel execution. More...
 
class  StageGroupBuilder
 Collects parallel kernels within a single stage group. More...
 
class  Stream
 An asynchronous work queue for device operations. More...
 
struct  ArgInfo_t
 
struct  KernelError_t
 
struct  Progress_t
 

Typedefs

using Profile = xpti::Profile
 

Enumerations

enum class  LogType {
  Resource , Execution , Internal , All ,
  NumLogType = All
}
 
enum class  LogLevel { Error , Info , Debug }
 
enum class  LogDetail { None , TimeStamp , CodeLocation , All }
 
enum class  LogOutput { Stdout , Stderr , File }
 
enum class  ArgDir : unsigned char { InOut , Input , Output }
 
enum class  ExecuteStatus {
  Idle = 0 , HostInit , DeviceInit , Request ,
  Waiting , DeviceFinalize , HostFinalize , Fail ,
  Cancelled , Completed , Max
}
 
enum class  ArgType { Constant , DeviceMemory , NDArray }
 
enum class  Result {
  Success = 0 , Failure , Pending , InvalidArgument ,
  DeviceError , NotFound , Timeout , NotSupported ,
  NotInitialized , Cancelled , Internal , Count
}
 
enum class  DeviceAttr {
  InfiniteMemory , NumClusterPerSub , NumMuCorePerCluster , TotalSubCount ,
  CxlMemoryCapacity , MappingGranularity
}
 
enum class  LocalityMode : uint32_t { CompactMode = 0 , SpreadMode }
 

Functions

void enableLog (const LogType &type, const LogLevel &level=LogLevel::Error, const LogDetail &detail=LogDetail::None)
 Configures logging settings for a specific log type. More...
 
void disableLog (const LogType &type)
 Disables logging for a specific log type. More...
 
void setOutput (const LogOutput &outputType, const char *filename=nullptr)
 Sets the output destination for log messages. More...
 
void registerSignalHandler (int32_t signalType)
 Registers a signal handler for a specific signal type. More...
 
void registerSignalHandler (const std::initializer_list< int32_t > &signalLists)
 Registers signal handlers for multiple signal types. More...
 
void flushHostCache (void *hostVirtualPtr, size_t size, bool opt=true)
 Flushes the host CPU cache for the specified memory range and records the range as written. More...
 
void flushHostCacheUntracked (void *hostVirtualPtr, size_t size, bool opt=true)
 Flushes the host CPU cache, and nothing else. More...
 
void invalidateHostCache (void *hostVirtualPtr, size_t size)
 Drops host cache lines over the range so a later read sees what the device wrote. More...
 
uint32_t getNumDevice ()
 Retrieves the number of available devices. More...
 
uint32_t availableSubCount (uint32_t deviceId)
 Returns the number of currently available compute resources (Subs) on a device, without creating a Context. More...
 
std::optional< uint32_t > getDefaultDeviceId ()
 Returns the current process-wide default device ID. More...
 
void clearDefaultDeviceId ()
 Clears the cached default device ID. More...
 
Context * createContext ()
 Creates a context. Defaults to the first available device. More...
 
Context * createContext (uint32_t deviceId)
 Creates a context for the specified device ID. More...
 
void destroyContext (Context *context)
 Destroys the specified context. More...
 
Module * createModule (const char *muBinaryPath)
 Creates a Module object from the specified MU binary path. More...
 
Module * createModule (const void *image)
 Creates a Module object from the specified MU binary image. More...
 
Module * createModule ()
 Creates a Module from the embedded kernel binary. More...
 
void destroyModule (Module *module)
 Destroys the specified Module object. More...
 
void registerKernelBinary (const void *start, const void *end)
 Registers an embedded kernel binary for automatic loading. More...
 
bool enableProfiling (const xpti::ProfileConfig &cfg)
 
void disableProfiling ()
 
bool isProfilingEnabled ()
 
Stream * createStream ()
 Creates a stream. More...
 
void destroyStream (Stream *stream)
 Destroys a stream. More...
 
const char * resultString (Result result) noexcept
 

Variables

constexpr const char * kAlreadyCalledMessage
 
constexpr const char * kNoDeviceResolvedMessage
 

Typedef Documentation

◆ Profile

using pxl::Profile = typedef xpti::Profile

Definition at line 35 of file profile.hpp.

Enumeration Type Documentation

◆ ArgDir

enum pxl::ArgDir : unsigned char
strong
Enumerator
InOut 
Input 
Output 

Definition at line 18 of file direction.hpp.

19 {
20  InOut,
21  Input,
22  Output,
23 };

◆ ArgType

enum pxl::ArgType
strong
Enumerator
Constant 
DeviceMemory 
NDArray 

Definition at line 27 of file type.hpp.

28 {
29  Constant,
31  NDArray,
32 };

◆ DeviceAttr

enum pxl::DeviceAttr
strong
Enumerator
InfiniteMemory 
NumClusterPerSub 
NumMuCorePerCluster 
TotalSubCount 
CxlMemoryCapacity 
MappingGranularity 

Definition at line 79 of file type.hpp.

80 {
86  // Job::remapMemory alignment. Reports NotSupported on devices that cannot
87  // remap (InfiniteMemory / non-CXL), so a successful query means remap is usable.
89 };

◆ ExecuteStatus

enum pxl::ExecuteStatus
strong
Enumerator
Idle 

Initial state before the first execution.

HostInit 
DeviceInit 
Request 
Waiting 
DeviceFinalize 
HostFinalize 
Fail 
Cancelled 
Completed 

The most recent execution completed successfully.

Max 

Definition at line 12 of file type.hpp.

13 {
14  Idle = 0,
15  HostInit,
16  DeviceInit,
17  Request,
18  Waiting,
21  Fail,
22  Cancelled,
23  Completed,
24  Max
25 };
@ Completed
The most recent execution completed successfully.
@ Idle
Initial state before the first execution.

◆ LocalityMode

enum pxl::LocalityMode : uint32_t
strong
Enumerator
CompactMode 
SpreadMode 

Definition at line 91 of file type.hpp.

92 {
93  CompactMode = 0,
95 };

◆ LogDetail

enum pxl::LogDetail
strong
Enumerator
None 
TimeStamp 
CodeLocation 
All 

Definition at line 31 of file config.hpp.

32 {
33  None,
34  TimeStamp,
36  All,
37 };

◆ LogLevel

enum pxl::LogLevel
strong
Enumerator
Error 
Info 
Debug 

Definition at line 24 of file config.hpp.

25 {
26  Error,
27  Info,
28  Debug,
29 };

◆ LogOutput

enum pxl::LogOutput
strong
Enumerator
Stdout 
Stderr 
File 

Definition at line 39 of file config.hpp.

40 {
41  Stdout,
42  Stderr,
43  File,
44 };

◆ LogType

enum pxl::LogType
strong
Enumerator
Resource 
Execution 
Internal 
All 
NumLogType 

Definition at line 15 of file config.hpp.

16 {
17  Resource,
18  Execution,
19  Internal,
20  All,
21  NumLogType = All
22 };

◆ Result

enum pxl::Result
strong
Enumerator
Success 
Failure 
Pending 
InvalidArgument 
DeviceError 
NotFound 
Timeout 
NotSupported 
NotInitialized 
Cancelled 
Internal 
Count 

Definition at line 54 of file type.hpp.

55 {
56  Success = 0,
57  Failure, // generic failure; prefer a specific category below when the cause is known
58  Pending,
59  // --- error categories (keep Success/Failure/Pending values stable; append only) ---
60  InvalidArgument, // malformed/contradictory caller input or object state
61  DeviceError, // HW/driver-level failure reported by xif
62  NotFound, // module/symbol/resource lookup miss
63  Timeout, // operation did not complete in time (e.g. waitEvent)
64  NotSupported, // unsupported request/configuration
65  NotInitialized, // library/context/device not initialized
66  Cancelled, // operation cancelled before completion
67  Internal, // internal invariant violated / unreachable (a PXL bug); always logged
68  // NOTE: memory-shortage failures are intentionally NOT represented here. They
69  // surface through the standalone memory API's MemoryStatus (memory.hpp), which
70  // is self-contained (no Result dependency) so the device can serve memory in
71  // InfiniteMemory mode without installing the full PXL library.
72  Count, // number of values; sentinel for iteration/tests, not a real status
73 };

Function Documentation

◆ availableSubCount()

uint32_t pxl::availableSubCount ( uint32_t  deviceId)

Returns the number of currently available compute resources (Subs) on a device, without creating a Context.

Parameters
deviceIdThe target device ID.
Returns
Available Sub count, or 0 if the device is unavailable.

◆ clearDefaultDeviceId()

void pxl::clearDefaultDeviceId ( )

Clears the cached default device ID.

After calling this, the next auto-device API call will re-resolve a default device (first-computable, with a first-any fallback for allocation).

◆ createContext() [1/2]

Context* pxl::createContext ( )

Creates a context. Defaults to the first available device.

Returns
Pointer to the created context, or nullptr if creation fails.

Example usage:

auto context = pxl::createContext();
Context * createContext()
Creates a context. Defaults to the first available device.

◆ createContext() [2/2]

Context* pxl::createContext ( uint32_t  deviceId)

Creates a context for the specified device ID.

Parameters
deviceIdThe ID of the device to create the context for.
Returns
Pointer to the created context, or nullptr if creation fails.

Example usage:

auto context = pxl::createContext(deviceId);

◆ createModule() [1/3]

Module* pxl::createModule ( )

Creates a Module from the embedded kernel binary.

Uses the binary registered by pxcc-generated static constructors via registerKernelBinary(). No explicit path or image pointer needed.

Returns
Pointer to the created Module object, or nullptr if no binary was registered or creation fails.

Example usage:

auto module = pxl::createModule();
auto func = module->createFunction<vectorAdd>();
Module * createModule(const char *muBinaryPath)
Creates a Module object from the specified MU binary path.

◆ createModule() [2/3]

Module* pxl::createModule ( const char *  muBinaryPath)

Creates a Module object from the specified MU binary path.

Parameters
muBinaryPathPath to the MU binary file.
Returns
Pointer to the created Module object, or nullptr if creation fails.

Example usage:

auto module = pxl::createModule("test.mubin");

◆ createModule() [3/3]

Module* pxl::createModule ( const void *  image)

Creates a Module object from the specified MU binary image.

Parameters
imagePointer to the MU binary image.
Returns
Pointer to the created Module object, or nullptr if creation fails.

◆ createStream()

Stream* pxl::createStream ( )

Creates a stream.

Returns
Pointer to the created stream, or nullptr if creation fails.

Example usage:

auto stream = pxl::createStream();
Stream * createStream()
Creates a stream.

◆ destroyContext()

void pxl::destroyContext ( Context *  context)

Destroys the specified context.

Parameters
contextPointer to the context to be destroyed.

Teardown waits for every Job's outstanding work. When called from a Map callback or createJobForceAsync() callback, this function cannot safely wait for that work. Instead, it retains the context and returns without destroying it.

A retained context keeps its Jobs, Subs, device memory, and stream slot. Its in-flight work continues, and callbacks may still run after this function returns. Keep all callback state alive until every Map has completed.

To release the context deterministically, call destroyContext() again from a thread that can wait. Otherwise, the next createContext() or destroyContext() call resumes the deferred teardown. If neither is called, library teardown resumes it. Do not use the context in the meantime. A call that resumes teardown may block until all of the retained context's work has completed.

Warning
Library teardown cannot defer retained contexts again. When it runs on a callback-delivery thread, it skips all Context and device cleanup and leaves those resources allocated until process exit.

Example usage:

void destroyContext(Context *context)
Destroys the specified context.

◆ destroyModule()

void pxl::destroyModule ( Module *  module)

Destroys the specified Module object.

Parameters
modulePointer to the Module object to be destroyed.

◆ destroyStream()

void pxl::destroyStream ( Stream *  stream)

Destroys a stream.

Parameters
streamPointer to the stream to be destroyed.

This function detaches the stream's consumer thread instead of joining it when the join would wait for work that the calling thread itself must deliver. This applies when called from the consumer thread, where this Stream's Map completion and error callbacks run, or from a frame that delivers a callback without publishing its own completion: a Map message callback or a createJobForceAsync() callback. All other callers join the consumer. This includes a completion or error callback that destroys a different Stream and an error callback invoked on the caller's thread when execute() fails to start.

After a detach, work already in the queue continues, and its callbacks may run after this function returns. The stream ID becomes available for reuse immediately, so createStream() may assign the same ID to a new Stream while the detached consumer is still draining. Creating another Stream before every Map on the destroyed Stream has completed is not supported. Keep callback state alive until all of that work has completed.

Example usage:

void destroyStream(Stream *stream)
Destroys a stream.

◆ disableLog()

void pxl::disableLog ( const LogType &  type)

Disables logging for a specific log type.

Parameters
typeType of log messages to disable.

Example usage:

void disableLog(const LogType &type)
Disables logging for a specific log type.

◆ disableProfiling()

void pxl::disableProfiling ( )

◆ enableLog()

void pxl::enableLog ( const LogType &  type,
const LogLevel &  level = LogLevel::Error,
const LogDetail &  detail = LogDetail::None 
)

Configures logging settings for a specific log type.

Parameters
typeType of log messages.
levelSeverity level of log messages (default: LogLevel::Error).
detailLevel of detail included in log messages (default: LogDetail::None).

Example usage:

void enableLog(const LogType &type, const LogLevel &level=LogLevel::Error, const LogDetail &detail=LogDetail::None)
Configures logging settings for a specific log type.

◆ enableProfiling()

bool pxl::enableProfiling ( const xpti::ProfileConfig &  cfg)

◆ flushHostCache()

void pxl::flushHostCache ( void *  hostVirtualPtr,
size_t  size,
bool  opt = true 
)

Flushes the host CPU cache for the specified memory range and records the range as written.

The record is a transfer-size hint. On a device without CXL coherency the runtime has to copy an argument's memory over before the kernel runs, and it cannot tell how much of the allocation the host touched — so it asks for the ranges flushed under that pointer and copies only those. Flush 4 KB inside a 1 GB allocation and the next Map::execute() copies 4 KB; flush nothing and it copies the whole gigabyte.

Warning
The record outlives the call, and a Map::execute() claiming it as covering an argument is the only thing that removes it — releasing the memory does not. So a caller that flushes in a loop without executing accumulates one record per distinct range for the life of the process, and every one of them is scanned on every other Map's execute. Worse, a record left behind by a freed buffer still matches by address, so an allocation that reuses that address can be claimed against the old, shorter range and silently transfer less than it should. Flush what an upcoming execute will read, not as a general-purpose cache operation in a hot loop.
Parameters
hostVirtualPtrPointer to the start of the memory range.
sizeSize of the memory range in bytes.
optEnable optimized flushing (default: true).
Warning
Not callable from a signal handler. Every call notes the range in a process-wide registry, which takes a mutex and allocates; a handler that interrupted the same thread inside that record re-acquires a non-recursive mutex on its own thread and sleeps forever. The window is small – the lock covers one push_back – but it is open on every platform, not just the emulator. Use flushHostCacheUntracked() there, and read its note first.

Example usage:

void flushHostCache(void *hostVirtualPtr, size_t size, bool opt=true)
Flushes the host CPU cache for the specified memory range and records the range as written.

◆ flushHostCacheUntracked()

void pxl::flushHostCacheUntracked ( void *  hostVirtualPtr,
size_t  size,
bool  opt = true 
)

Flushes the host CPU cache, and nothing else.

The same cache operation as flushHostCache() without the record it keeps.

Note
On real hardware this is the variant a signal handler may call. flushHostCache() reaches a process-wide registry to note the range, and that registry is mutex-protected – taking a lock from a handler can deadlock against the code the signal interrupted. This one skips the registry and reduces to a CLFLUSHOPT loop plus a fence, and it is deliberately left out of the public-API tracing, because that tracing takes a lock and allocates when it is switched on.
Warning
Under the emulator the cache operation is an ioctl instead, and the host address has to be translated for it. That translation goes through MemoryLibrary::isManaged(), which takes the allocation map's mutex on every call – not just the first. A handler that calls this while the interrupted code was inside that lookup re-acquires a non-recursive mutex on its own thread and sleeps forever.

Measured on the emulator: it deadlocks, and it does so whatever the range is – the lock sits in front of the managed/unmanaged decision, so even an address this library never allocated hangs. So there is no signal-safe way to publish a host write there yet, and the warm-up below does not create one; it only removes the first-call cost. This is tracked, not settled: see issue #580. Do not read the paragraph above as the intended end state.

Call it once on the normal path before relying on it from a handler. This is not an emulator-only step: the platform check in front of the cache operation resolves a singleton on first use, and that construction reads a sysfs file through std::ifstream, so the first call allocates on real hardware too. Every call after it is the CLFLUSHOPT loop alone.

Also the one to prefer on any path that runs repeatedly, for a second reason: flushHostCache()'s record is removed only when a Map::execute() claims it as covering an argument, so a caller that flushes in a loop without executing again grows that registry for the life of the process.

Parameters
hostVirtualPtrPointer to the start of the memory range.
sizeSize of the memory range in bytes.
optEnable optimized flushing (default: true).
Note
This recipe assumes your own handler. registerSignalHandler() installs one that reports and exits instead of setting a flag, and std::signal keeps one handler per signal, so registering it for the same signal replaces this.

Example usage:

control->stop = 1;
pxl::flushHostCacheUntracked(&control->stop, sizeof(control->stop));
void flushHostCacheUntracked(void *hostVirtualPtr, size_t size, bool opt=true)
Flushes the host CPU cache, and nothing else.

◆ getDefaultDeviceId()

std::optional<uint32_t> pxl::getDefaultDeviceId ( )

Returns the current process-wide default device ID.

The default device is updated implicitly by successful explicit-device API calls (e.g. allocateMemory(deviceId, ...), createContext(deviceId), Launcher(deviceId)) and consumed by auto-device API calls (allocateMemory(size_t), createContext(), Launcher()).

Returns
The current default device ID, or std::nullopt if none has been set.

◆ getNumDevice()

uint32_t pxl::getNumDevice ( )

Retrieves the number of available devices.

Returns
Number of available devices.

Example usage:

auto numDevices = pxl::getNumDevice();
uint32_t getNumDevice()
Retrieves the number of available devices.

◆ invalidateHostCache()

void pxl::invalidateHostCache ( void *  hostVirtualPtr,
size_t  size 
)

Drops host cache lines over the range so a later read sees what the device wrote.

The counterpart to flushHostCache(): that one publishes host writes to the device, this one lets the host observe device writes. Needed to read a value the device produced — a completion counter the kernel bumps, for instance. A flush is not a substitute: on the QEMU device model the two are different ioctls, and flushing there leaves the host reading its own stale line.

Warning
The range must hold no dirty host lines — either the device is its only writer, or the host flushed it and has not touched it since. On x86 CLFLUSHOPT writes a dirty line back before invalidating it, so a dirty line here overwrites the device's data.

The operation is widened to whole cache lines, so keep a device-written field on its own cache line if the host writes anything adjacent. A size of 0 is a no-op for the same reason: widening an empty range would reach a line the caller asked nothing about, and the warning above applies to that line too.

Note
Returns void, like the two flushes beside it, and on real hardware that loses nothing: the call is a CLFLUSHOPT loop with no failure mode. Under the emulator it can be skipped whole — /dev/xcena_cache not open, or the address not one this library allocated — and the caller then reads a stale line with no way to tell from the call. The error log is the only signal there, so check it before trusting a device-written value read back under the emulator.
Parameters
hostVirtualPtrPointer to the start of the memory range.
sizeSize of the memory range in bytes.

Example usage:

pxl::invalidateHostCache(&control->doneCount, sizeof(control->doneCount));
const uint32_t done = control->doneCount;
void invalidateHostCache(void *hostVirtualPtr, size_t size)
Drops host cache lines over the range so a later read sees what the device wrote.

◆ isProfilingEnabled()

bool pxl::isProfilingEnabled ( )

◆ registerKernelBinary()

void pxl::registerKernelBinary ( const void *  start,
const void *  end 
)

Registers an embedded kernel binary for automatic loading.

Called by pxcc-generated static constructors to register a kernel binary (.mubin) that has been embedded into the host executable at link time. Only the first registration takes effect; subsequent calls are ignored.

Parameters
startPointer to the start of the embedded binary data.
endPointer to the end of the embedded binary data.

◆ registerSignalHandler() [1/2]

void pxl::registerSignalHandler ( const std::initializer_list< int32_t > &  signalLists)

Registers signal handlers for multiple signal types.

Parameters
signalTypesInitializer list of signal types to handle.

Example usage:

pxl::registerSignalHandler({SIGSEGV, SIGABRT, SIGFPE});
void registerSignalHandler(int32_t signalType)
Registers a signal handler for a specific signal type.

◆ registerSignalHandler() [2/2]

void pxl::registerSignalHandler ( int32_t  signalType)

Registers a signal handler for a specific signal type.

Warning
The installed handler reports and terminates the process; it is a crash reporter, not a place to run shutdown work, and what it calls is not async-signal-safe. std::signal keeps one handler per signal, so this replaces any handler of your own on the same signal — including one that publishes a stop flag with flushHostCacheUntracked().
Parameters
signalTypeType of signal to handle.

Example usage:

◆ resultString()

const char* pxl::resultString ( Result  result)
noexcept

◆ setOutput()

void pxl::setOutput ( const LogOutput &  outputType,
const char *  filename = nullptr 
)

Sets the output destination for log messages.

Parameters
outputTypeOutput destination (e.g., Stdout, Stderr, or File).
filenameName of the file to output log messages to (only applicable if outputType is File).

Example usage:

void setOutput(const LogOutput &outputType, const char *filename=nullptr)
Sets the output destination for log messages.

Variable Documentation

◆ kAlreadyCalledMessage

constexpr const char* pxl::kAlreadyCalledMessage
inlineconstexpr
Initial value:
=
"run/runAsync already called on this builder"

Definition at line 22 of file launch_result.hpp.

◆ kNoDeviceResolvedMessage

constexpr const char* pxl::kNoDeviceResolvedMessage
inlineconstexpr
Initial value:
=
"No device resolved — pointer arguments must come from pxl::allocateMemory(), "
"or use Launcher(deviceId) for scalar-only kernels"

Definition at line 31 of file launch_result.hpp.