1. Virtual Machine#
The PISA virtual machine is an execution environment that dictates how PISA kernels are structured, launched, and run, largely following the OpenCL 3.0 execution model.
1.1. Execution Model#
A PISA kernel is a sequence of instructions that executes on the PISA
virtual machine. When the host program submits a kernel for execution,
the PISA virtual machine creates an N-Dimensional Range (NDRange) of work-items,
and an instance of the kernel is created for each element in the NDRange.
In addition to the total number of work-items (global size), the host
program may also specify how many work-items to group together into work-groups
(local size). Work-items in the same work-group can communicate
through objects in the shared memory, and they can synchronize through
the barrier instructions. During execution, each work-group is further
divided by the virtual machine into one or more sub-groups, and
work-items within a sub-group can communicate and synchronize through
shuffle, reduce, and barrier instructions. A value or variable is
considered sub-group-uniform if it is guaranteed to have the same
value across all active work-items within a sub-group.
Note
Special registers can be used to query the sub-group, local, and global sizes, as well as work-item IDs.
1.1.1. Order of Execution#
The PISA virtual machine executes work-groups concurrently but not necessarily in parallel, and their execution order is unspecified. Work-items in the same work-group execute as members of the same work-group instance and may synchronize and communicate through work-group-level mechanisms, but the virtual machine does not require any particular issue order among them. Sub-groups within the same work-group maintain independent forward progress with respect to each other. In other words, unless one sub-group depends on another sub-group, for example by waiting at a work-group barrier, its execution must not be blocked by that other sub-group.
1.2. Memory Model#
PISA memory objects may be stored in one of the supported address spaces.
global memory (visible to all work-items)
constant memory (visible to all work-items)
shared local memory (visible to work-items in the same work-group)
private memory (visible to this work-item only)
parameter memory (kernel arguments, visible to all work-items)
Note
All address spaces, except for register and parameter, follow the OpenCL definitions.
1.2.1. Memory Consistency#
The PISA memory consistency model follows the C++ memory model and extends it
with explicit memory scopes. Memory accesses may be non-atomic (weak) or
atomic with a memory order. weak accesses provide no ordering or atomicity
guarantees. relaxed atomic accesses impose no ordering constraints;
stronger orders establish happens-before relationships across work-items.
1.2.1.1. Memory Order#
Atomic memory instructions carry a memory order that establishes happens-before relationships across work-items. Memory order can also be combined with a scope on a fence instruction to order relaxed memory operations.
Note
weak is not a memory order. It marks a non-atomic access with no atomicity or
ordering guarantees. Use relaxed or a stronger order for atomic accesses.
PISA Memory Order |
C++ equivalent |
|---|---|
relaxed |
memory_order_relaxed |
acquire |
memory_order_acquire |
release |
memory_order_release |
acq_rel |
memory_order_acq_rel |
seq_cst |
memory_order_seq_cst |
Important
Memory order may only be specified on access to global or shared memory objects.
1.2.1.2. Memory Scope#
Memory scope specifies the set of work-items in which a memory instruction
can directly synchronize. A memory scope must be specified when the memory order is
stronger than relaxed (i.e., acquire, release, acq_rel, or seq_cst).
It can also be combined with a fence instruction to establish
ordering of relaxed memory accesses across the work-items in the specified scope.
PISA Memory Scope |
Description |
|---|---|
|
All work-items in the same sub-group |
|
All work-items in the same work-group |
|
All work-items in the global NDRange |
|
All work-items in the global NDRange and the host program |
Important
Memory scope may only be specified on access to global or shared memory objects.