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
Source: 3rdparty/shmem/src/python/shmem/__init__.py
For comprehensive ACLSHMEM documentation, refer to the ACLSHMEM docs.
Initialization and Finalization
aclshmem_init
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- my_pe() int
Get the PE number of the calling process.
- Returns:
int — PE number (0 to pe_count()-1)
pe_count
- pe_count() int
Get the total number of PEs.
- Returns:
int — Total number of PEs in the system
Host RMA Operations
aclshmem_putmem
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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_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_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_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
InitAttr
InitStatus
- class InitStatus
Status object returned by initialization functions.
OpEngineType
- class OpEngineType
Enum for operation engine types.
aclshmem_info_get_version
- aclshmem_info_get_version() str
Get the ACLSHMEM library version string.
- Returns:
str — Version string
aclshmem_info_get_name
- aclshmem_info_get_name() str
Get the ACLSHMEM library name.
- Returns:
str — Library name
set_log_level
- set_log_level(level: int) None
Configure ACLSHMEM logging level.
- Parameters:
level – Logging level (use standard Python logging levels)
Utility Functions
aclshmem_global_exit
- 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
- 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
- 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.