Programming Objects
A PXL host application is built from four objects: Context, Job, Module, and Function. They form a creation chain — each object is produced from the one above it.
pxl::createContext() → Context
└─ createJob() → Job
└─ load(module) / buildMap(...)
pxl::createModule(path) → Module
└─ createFunction(name) → Function
Map is created from a Job and is covered in Kernel Execution. Stream is covered in Streams.
Context
A Context is an execution session bound to a device. It owns device memory and is the factory for Jobs.
Responsibilities:
- Create and destroy
Jobs. - Allocate, free, and transfer device memory.
- Query memory information of a pointer.
auto ctx = pxl::createContext(); // first available device
auto ctx0 = pxl::createContext(deviceId); // specific device
// Device memory
auto ptr = ctx->memAlloc(size);
ctx->copyToDevice(ptr, hostBuf, size);
ctx->copyFromDevice(hostBuf, ptr, size);
ctx->memFree(ptr);
// Job creation
auto job = ctx->createJob(numSub);
pxl::destroyContext(ctx);
Reuse a single
Contextfor the lifetime of your application. Allocating device memory once at startup and reusing it across kernel launches avoids re-mapping device addresses on every launch, which would otherwise add latency to each call.
Job
A Job is a reservation of one or more Sub units. It loads a kernel binary and creates Map objects that run on those Subs.
Responsibilities:
- Hold a set of Subs (allocate more or release some at runtime).
- Load a
Moduleso the kernel binary lives on the Job’s Subs. - Build
Mapobjects that target functions in the loaded module. - Own a private default
Streamused by everyMapthat does not bind its own.
auto job = ctx->createJob(4); // 4 Subs
job->load("mu_kernel.mubin"); // load by path
// or: job->load(module); // load a pre-created Module
job->subAlloc(2); // request 2 more Subs
auto subIds = job->subIdList(); // inspect what was assigned
auto map = job->buildMap("my_kernel", taskCount);
ctx->destroyJob(job);
Destroying a Job synchronously drains every
Mapbuilt from it, so it is safe to call even when asynchronous executions are still in flight.
Module and Function
A Module is a compiled MU kernel binary. A Function is a single host-callable entry point inside that module.

auto module = pxl::createModule("mu_kernel.mubin");
auto sortFunc = module->createFunction("bubbleSort");
auto searchFunc = module->createFunction("binarySearch");
// Inspect the module
auto names = module->getMuFunctionList();
auto count = module->getNumMuFunctions();
pxl::destroyModule(module);
A Module can be loaded into a Job with job->load(module). The Job’s Subs then hold the binary, so buildMap(funcName, ...) can resolve function names against it.
Lifecycle Summary
| Object | Created by | Destroyed by | Owns |
|---|---|---|---|
Context | pxl::createContext() | pxl::destroyContext() | device memory, Jobs |
Job | Context::createJob() | Context::destroyJob() | Subs, default Stream, Maps |
Module | pxl::createModule() | pxl::destroyModule() | binary image, Functions |
Function | Module::createFunction() | Module::destroyFunction() | (handle only) |
Map | Job::buildMap() | Job::destroyMap() | argument bindings, stream binding |
Destroying a parent object releases its children, so you typically only need to destroy the top-level objects (Context, Module). Explicit child destruction is supported for cases where you want to free resources earlier.
→ Related: Kernel Execution, Streams