SHMEM Host API¶
This module provides host-side ACLSHMEM operations for initializing the SHMEM runtime, managing symmetric memory, and performing host-initiated communication. These APIs are called from Python host code, not from within kernels.
The ACLSHMEM package must be installed separately. Install with:
pip install aclshmem
All host APIs are available through:
import shmem
For comprehensive ACLSHMEM documentation, refer to the ACLSHMEM docs.
Initialization and Finalization¶
- aclshmem_init(attributes: InitAttr) InitStatus¶
Initialize the ACLSHMEM runtime with specified attributes.
- Parameters:
attributes – InitAttr object containing initialization configuration
- Returns:
InitStatus — Status object containing initialization results
Must be called before any other SHMEM operations. Each PE must call this function.
Example:
import shmem attr = shmem.InitAttr() attr.mem_size = 1024 * 1024 * 1024 # 1GB symmetric heap status = shmem.aclshmem_init(attr)
- aclshmem_finalize() None¶
Finalize and clean up the ACLSHMEM runtime.
Must be called by all PEs before program termination. Releases all symmetric memory and communication resources. After calling this, no other SHMEM operations can be performed.
Example:
# At program end shmem.aclshmem_finalize()
- aclshmem_init_using_unique_id(rank: int, nranks: int, mem_size: int, uid: bytes) InitStatus¶
Initialize ACLSHMEM using a unique ID for multi-process coordination.
- Parameters:
rank – Rank number of this process (0 to nranks-1)
nranks – Total number of processes/ranks
mem_size – Size of symmetric heap in bytes
uid – Unique ID bytes obtained from aclshmem_get_unique_id()
- Returns:
InitStatus — Initialization status
Usage Pattern:
import shmem # On rank 0: generate and broadcast unique ID if rank == 0: uid = shmem.aclshmem_get_unique_id() # ... broadcast uid to all ranks ... else: # ... receive uid from rank 0 ... pass # All ranks initialize with the same uid status = shmem.aclshmem_init_using_unique_id( rank, nranks, mem_size=1024*1024*1024, uid=uid )
- aclshmem_get_unique_id() bytes¶
Generate a unique ID for coordinating multi-process SHMEM initialization.
- Returns:
bytes — Unique identifier to be shared across all processes
Typically called by rank 0 and broadcast to other ranks. The same unique ID must be used by all participating processes.
Memory Management¶
- aclshmem_malloc(nbytes: int) int¶
Allocate symmetric memory from the SHMEM heap.
- Parameters:
nbytes – Number of bytes to allocate
- Returns:
int — Pointer (as integer) to the allocated memory, or 0 on failure
Memory is allocated at the same offset in the symmetric heap on all PEs. All PEs must call this with the same
nbytesvalue. Use this for memory that will be accessed remotely via RMA operations.Example:
# Allocate 4MB of symmetric memory ptr = shmem.aclshmem_malloc(4 * 1024 * 1024) if ptr == 0: raise RuntimeError("Symmetric memory allocation failed")
- aclshmem_free(ptr: int) None¶
Free symmetric memory previously allocated with
aclshmem_malloc.- Parameters:
ptr – Pointer (as integer) to the memory to free
All PEs must free symmetric allocations collectively. Do not free memory that was not allocated with
aclshmem_malloc.
- aclshmem_calloc(count: int, size: int) int¶
Allocate and zero-initialize symmetric memory.
- Parameters:
count – Number of elements
size – Size of each element in bytes
- Returns:
int — Pointer to allocated memory, or 0 on failure
Equivalent to
aclshmem_malloc(count * size)followed by zeroing. All PEs must call with the same parameters.
- aclshmem_align(alignment: int, size: int) int¶
Allocate aligned symmetric memory.
- Parameters:
alignment – Alignment requirement in bytes (must be power of 2)
size – Number of bytes to allocate
- Returns:
int — Pointer to aligned memory, or 0 on failure
Example:
# Allocate 1MB aligned to 4KB boundary ptr = shmem.aclshmem_align(4096, 1024 * 1024)
- aclshmem_ptr(local_ptr: int, pe: int) int¶
Get a pointer to a symmetric object on a remote PE (host-accessible).
- Parameters:
local_ptr – Local pointer to symmetric memory
pe – Target PE number
- Returns:
int — Pointer that can be used on the host to access the symmetric object on the specified PE, or 0 if not accessible
May return 0 for inter-node remote pointers if direct host access is not supported. Primarily useful for intra-node scenarios.
- aclshmemx_get_heap_base() int¶
Get the base address of the symmetric heap.
- Returns:
int — Base address of the symmetric heap
PE Information¶
- my_pe() int
Get the PE number of the calling process.
- Returns:
int — PE number (0 to pe_count()-1)
- pe_count() int¶
Get the total number of PEs.
- Returns:
int — Total number of PEs in the system
Host RMA Operations¶
- aclshmem_putmem(dest: int, source: int, bytes: int, pe: int) None¶
Host-side blocking put (write) to remote symmetric memory.
- Parameters:
dest – Destination pointer on remote PE
source – Source pointer on local host
bytes – Number of bytes to transfer
pe – Target PE number
Example:
import numpy as np import shmem # Allocate symmetric memory remote_buf = shmem.aclshmem_malloc(1024) # Create host data data = np.arange(256, dtype=np.float32) # Put data to PE 1 shmem.aclshmem_putmem(remote_buf, data.ctypes.data, data.nbytes, pe=1)
- aclshmem_getmem(dest: int, source: int, bytes: int, pe: int) None¶
Host-side blocking get (read) from remote symmetric memory.
- Parameters:
dest – Destination pointer on local host
source – Source pointer on remote PE
bytes – Number of bytes to transfer
pe – Source PE number
- aclshmem_putmem_nbi(dest: int, source: int, bytes: int, pe: int) None¶
Host-side non-blocking put to remote symmetric memory.
- Parameters:
dest – Destination pointer on remote PE
source – Source pointer on local host
bytes – Number of bytes to transfer
pe – Target PE number
Operation may complete asynchronously. Use appropriate synchronization before reusing source buffer or assuming remote visibility.
- aclshmem_getmem_nbi(dest: int, source: int, bytes: int, pe: int) None¶
Host-side non-blocking get from remote symmetric memory.
- Parameters:
dest – Destination pointer on local host
source – Source pointer on remote PE
bytes – Number of bytes to transfer
pe – Source PE number
- aclshmemx_putmem_signal(dest: int, source: int, nbytes: int, sig_addr: int, signal: int, sig_op: int, pe: int) None¶
Host-side blocking put with atomic signal operation on completion.
- Parameters:
dest – Destination pointer on remote PE
source – Source pointer on local host
nbytes – Number of bytes to transfer
sig_addr – Signal address on remote PE
signal – Signal value
sig_op – Signal operation (SET or ADD)
pe – Target PE number
- aclshmemx_putmem_signal_nbi(dest: int, source: int, nbytes: int, sig_addr: int, signal: int, sig_op: int, pe: int) None¶
Host-side non-blocking put with signal.
- Parameters:
dest – Destination pointer on remote PE
source – Source pointer on local host
nbytes – Number of bytes to transfer
sig_addr – Signal address on remote PE
signal – Signal value
sig_op – Signal operation (SET or ADD)
pe – Target PE number
- aclshmem_signal_wait_until(sig_addr: int, cmp: int, cmp_val: int) None¶
Host-side wait on a signal location until a condition is met.
- Parameters:
sig_addr – Pointer to signal location
cmp – Comparison operation (see device API for constants)
cmp_val – Comparison value
Team Management¶
- team_split_strided(start: int, stride: int, size: int, parent_team) team¶
Create a new team by selecting PEs with a strided pattern from the parent team.
- Parameters:
start – Starting PE in parent team
stride – Stride between selected PEs
size – Number of PEs in new team
parent_team – Parent team handle
- Returns:
Team handle for the newly created team
Example:
# Create team with PEs 0, 2, 4, 6 from global team team = shmem.team_split_strided( start=0, stride=2, size=4, parent_team=shmem.SHMEM_TEAM_WORLD )
- team_split_2d(xdim: int, xaxis_teams, ydim: int, yaxis_teams) None¶
Split PEs into 2D grid of teams.
- Parameters:
xdim – Size of X dimension
xaxis_teams – Output array for X-axis teams
ydim – Size of Y dimension
yaxis_teams – Output array for Y-axis teams
- team_translate_pe(src_team, src_pe: int, dest_team) int
Translate a PE number from one team to another.
- Parameters:
src_team – Source team handle
src_pe – PE number in source team
dest_team – Destination team handle
- Returns:
int — Corresponding PE number in destination team
- team_my_pe(team) int
Get the calling PE’s number within the specified team.
- Parameters:
team – Team handle
- Returns:
int — PE number within the team
- team_n_pes(team) int
Get the number of PEs in the specified team.
- Parameters:
team – Team handle
- Returns:
int — Number of PEs in the team
- team_destroy(team) None¶
Destroy a team and release its resources.
- Parameters:
team – Team handle to destroy
Do not destroy predefined teams. All PEs in the team must call this collectively.
Configuration and Info¶
- class InitAttr¶
Initialization attributes class for configuring ACLSHMEM runtime.
Attributes:
- mem_size¶
Size of symmetric heap in bytes
- class InitStatus¶
Status object returned by initialization functions.
- class OpEngineType¶
Enum for operation engine types.
- aclshmem_info_get_version() str¶
Get the ACLSHMEM library version string.
- Returns:
str — Version string
- aclshmem_info_get_name() str¶
Get the ACLSHMEM library name.
- Returns:
str — Library name
- set_log_level(level: int) None¶
Configure ACLSHMEM logging level.
- Parameters:
level – Logging level (use standard Python logging levels)
Utility Functions¶
- aclshmem_global_exit(status: int) None¶
Perform a global exit of all PEs with the specified status code.
- Parameters:
status – Exit status code
Terminates all PEs in the SHMEM job. Use for coordinated error handling.
- aclshmem_create_tensor(shape: tuple, dtype: torch.dtype = torch.float32, device_id: int = 0) torch.Tensor¶
Create a PyTorch tensor backed by symmetric memory.
- Parameters:
shape – Tensor shape tuple
dtype – PyTorch data type (default: torch.float32)
device_id – NPU device ID (default: 0)
- Returns:
torch.Tensor — Tensor backed by symmetric memory
Example:
import torch import shmem # Create symmetric tensor tensor = shmem.aclshmem_create_tensor( (1024, 1024), dtype=torch.float32, device_id=0 ) # Use like any other PyTorch tensor tensor.fill_(0.0)
- aclshmem_free_tensor(tensor: torch.Tensor) None¶
Free the symmetric memory backing a tensor created with
aclshmem_create_tensor.- Parameters:
tensor – Tensor to free
Only use with tensors created via
aclshmem_create_tensor. Tensor should not be used after calling this function.
Complete Example¶
import shmem
import torch
import numpy as np
# Initialize SHMEM
attr = shmem.InitAttr()
attr.mem_size = 1024 * 1024 * 1024 # 1GB
status = shmem.aclshmem_init(attr)
# Get PE info
my_rank = shmem.my_pe()
num_ranks = shmem.pe_count()
print(f"PE {my_rank} of {num_ranks}")
# Allocate symmetric memory
sym_ptr = shmem.aclshmem_malloc(1024 * 1024) # 1MB
if sym_ptr == 0:
raise RuntimeError("Failed to allocate symmetric memory")
# Or create symmetric tensor
sym_tensor = shmem.aclshmem_create_tensor((1024, 256), dtype=torch.float32)
# Perform communication
if my_rank == 0:
# Rank 0 sends data to rank 1
data = np.arange(256, dtype=np.float32)
if num_ranks > 1:
shmem.aclshmem_putmem(sym_ptr, data.ctypes.data, data.nbytes, pe=1)
elif my_rank == 1:
# Rank 1 receives (data is already in symmetric memory)
pass
# Clean up
shmem.aclshmem_free_tensor(sym_tensor)
shmem.aclshmem_free(sym_ptr)
shmem.aclshmem_finalize()
Installation Notes¶
The ACLSHMEM package is distributed separately and must be installed:
pip install aclshmem
Or build from source in the 3rdparty/shmem directory. See the Build from Source
guide for details.
Notes¶
Symmetric Memory Model¶
SHMEM uses a symmetric memory model where allocations occur at the same virtual address offset on all PEs. This enables efficient remote memory access without explicit address translation.
Collective Operations¶
Many SHMEM operations are collective and must be called by all PEs in the team or globally. Examples include:
aclshmem_init/aclshmem_finalizeaclshmem_malloc/aclshmem_freeBarrier operations
Team creation and destruction
Thread Safety¶
SHMEM operations are generally not thread-safe. If using multiple threads per PE, appropriate synchronization must be added by the application.