Skip to main content

ibverbs

Low-level, Pythonic bindings for libibverbs (RDMA), designed as a foundation for building high-performance RDMA libraries in Python — including GPUDirect transfers to/from GPU memory.

The bindings are a thin, faithful wrapper over the verbs API (device, PD, MR, CQ, QP, SRQ, AH, work requests, completions, async events) plus a small, optional set of RC connection helpers. They are written in Cython so the data path (post_send / post_recv / poll) compiles to direct C calls and releases the GIL, and so the static inline verbs fast-path functions are called correctly (they can't be reached through dlsym).

  • No runtime dependencies. Only libibverbs, which is dlopened at import.
  • No torch / CUDA linkage. GPUDirect works by registering an integer device address or an exported dma-buf fd; CUDA stays entirely in your code.
  • One abi3 wheel for all of CPython 3.9+ on Linux.

Portability

The extension does not link libibverbs. It is compiled against the rdma-core headers (for struct layouts and the static inline data-path verbs) but resolves the exported verbs at import time with dlopen/dlsym. As a result:

  • The compiled module's only NEEDED library is libc — no external dependency for auditwheel, so a single manylinux wheel is portable across distros.
  • It is built against the CPython Limited API (abi3), so one wheel works on CPython 3.9 through 3.14+ — no per-version builds.
  • A missing libibverbs yields a clean ImportError, not a loader crash.
  • Newer verbs are optional: ibv_reg_dmabuf_mr (rdma-core ≥ 34) is loaded if present and only errors if you actually call reg_dmabuf_mr, so the wheel still imports on older systems.
  • RDMA-CM is optional and lazily loads librdmacm.so.1 only when CMID is used. CMID.resolve() returns the CM-owned device context and creates QPs whose state transitions and destruction remain owned by librdmacm.

Base verbs use only libibverbs.so.1 at runtime (any rdma-core from the last several years); CMID additionally needs librdmacm.so.1. The data path (post_send/poll/…) stays compiled inline and dispatches through the provider op table, so dlopen costs nothing on the hot path.

Requirements

  • Linux with an RDMA-capable NIC (tested on Mellanox/NVIDIA mlx5, RoCEv2).
  • Runtime: libibverbs.so.1 (rdma-corelibibverbs1 on Debian/Ubuntu, libibverbs on RHEL/Fedora). No compiler or headers needed to use a wheel.
  • Build from source only: a C compiler, Cython, and the rdma-core development headers (libibverbs-dev plus librdmacm-dev on Debian/Ubuntu, or rdma-core-devel on RPM-based distributions).

Install

pip install ibverbs        # prebuilt abi3 manylinux wheel

Building from source (needs the rdma-core dev headers + a compiler):

pip install "Cython>=3.0" "setuptools>=77" wheel
pip install ./ibverbs       # or: pip install -e ./ibverbs

Quickstart

import ibverbs as ib

# 1. Open a device and set up resources.
dev = ib.get_device_list()[0]
ctx = dev.open()
pd = ctx.alloc_pd()
cq = ctx.create_cq(64)

# 2. Register memory (host or GPU address — any integer VA works).
import numpy as np
buf = np.zeros(4096, dtype=np.uint8)
access = ib.AccessFlags.LOCAL_WRITE | ib.AccessFlags.REMOTE_WRITE | ib.AccessFlags.REMOTE_READ
mr = pd.reg_mr(buf.ctypes.data, buf.nbytes, access)

# 3. Create a reliable-connected QP.
qp = pd.create_qp(ib.QPInitAttr(send_cq=cq, recv_cq=cq, qp_type=ib.QPType.RC))

# 4. Exchange connection info with the peer out-of-band, then connect.
port = 1
port_attr = ctx.query_port(port)
gid = ctx.query_gid(port, gid_index)              # pick a routable RoCEv2 GID
local = ib.local_qp_info(qp, port_attr, gid, port=port, psn=0)
# ... send local.to_bytes() to peer, receive remote_bytes ...
remote = ib.QPInfo.from_bytes(remote_bytes)
ib.connect_rc(qp, remote, port=port, sgid_index=gid_index, access=access)

# 5. Post an RDMA write and reap the completion.
qp.post_send(ib.SendWR(
    wr_id=1, sg_list=[ib.SGE(mr, 4096)], opcode=ib.WROpcode.RDMA_WRITE,
    send_flags=ib.SendFlags.SIGNALED, remote_addr=peer_addr, rkey=peer_rkey))
for wc in cq.poll(16):
    wc.raise_for_status()

Every resource is a context manager and frees its handle on close() / garbage collection; children hold references to their parents, so destruction order is always safe.

GPUDirect with torch tensors

The library never imports torch or links CUDA. The optional ibverbs.cuda helper (which only lazily dlopens libcuda) registers a CUDA tensor for RDMA in one call — handling the dma-buf export and page alignment for you:

import os
# torch's CUDA memory must be VMM-backed to be dma-buf exportable. Set this
# BEFORE torch initializes CUDA:
os.environ["PYTORCH_CUDA_ALLOC_CONF"] = "expandable_segments:True"

import torch
import ibverbs as ib
import ibverbs.cuda

src = torch.arange(4096, dtype=torch.float32, device="cuda:0")
dst = torch.zeros(4096, dtype=torch.float32, device="cuda:0")

access = ib.AccessFlags.LOCAL_WRITE | ib.AccessFlags.REMOTE_WRITE
src_mr = ib.cuda.register_tensor(pd, src, access)   # retains src until close()
dst_mr = ib.cuda.register_tensor(pd, dst, access)

# RDMA-write one GPU buffer into another, with no host staging on the data path.
torch.cuda.synchronize(src.device)  # source-producing CUDA work must be done
qp.post_send(ib.SendWR(
    wr_id=1, sg_list=[src_mr.sge()], opcode=ib.WROpcode.RDMA_WRITE,
    send_flags=ib.SendFlags.SIGNALED,
    remote_addr=dst_mr.addr, rkey=dst_mr.rkey))
for wc in qp.send_cq.poll(16):
    wc.raise_for_status()

# On the receiver, after the peer has signaled that its write is complete,
# order the inbound NIC writes before launching CUDA work that consumes dst.
with torch.cuda.device(dst.device):
    ib.cuda.flush_gpudirect_writes()

GpuMR wraps the MR with the correct device address (ibv_mr.addr is not meaningful for dma-buf MRs), retains the tensor allocation until close(), and exposes .sge(), .addr, .lkey, .rkey.

CUDA work and NIC work are separate ordering domains. Synchronize the stream that produced an outbound tensor before posting it. For inbound SEND, RDMA read, or RDMA write, wait for the corresponding completion or protocol-level notification, then call flush_gpudirect_writes() in the destination CUDA context before consuming the tensor. A one-sided RDMA write does not create a remote CQ entry by itself; use write-with-immediate or an out-of-band message to notify the receiver.

Under the hood there are two registration paths, chosen automatically:

# dma-buf fd (default; no kernel module needed):
mr = pd.reg_dmabuf_mr(offset, length, iova=device_va, fd=dmabuf_fd, access=access)
# raw device pointer (requires the nvidia_peermem kernel module):
mr = pd.reg_mr(tensor.data_ptr(), nbytes, access)

For a host (CPU) torch tensor or numpy array, ib.reg_tensor(pd, tensor, access) registers it directly and retains the allocation. Both tensor helpers require contiguous, non-empty tensors; split any single SGE larger than 2**32 - 1 bytes into multiple entries. tests/test_gpudirect.py performs real GPU-to-GPU RDMA writes, reads, and sends verified with torch.equal.

Feature coverage

Area Supported
Device / port / GID query get_device_list, Context.query_device/query_port/query_gid
Protection domains alloc_pd
Memory regions reg_mr, reg_dmabuf_mr (GPUDirect)
Completion queues create_cq, poll, comp channels + req_notify/ack_events
Queue pairs ✅ RC / UC / UD; modify, query, to_init/to_rtr/to_rts
Work requests ✅ SEND(/_IMM), RDMA_WRITE(/_IMM), RDMA_READ, ATOMIC_CMP_AND_SWP, ATOMIC_FETCH_AND_ADD, scatter/gather, inline/signaled/fenced/solicited flags
Shared receive queues create_srq, post_recv, modify, query
Address handles create_ah (UD)
Async events get_async_event / ack_async_event, async_fd
Connection helpers QPInfo, local_qp_info, connect_rc
RDMA connection manager CMID.resolve/create_qp/connect/disconnect

Out of scope for v1 (candidates for later): the extended ibv_wr_* / qp_ex post API, device memory (ibv_alloc_dm), memory windows, and flow steering.

Testing

The suite exercises real hardware and skips features the host lacks:

pip install -e "./ibverbs[test,gpu]"     # pytest, numpy, torch
cd ibverbs && pytest -rs                  # -rs shows skip reasons
pytest -m "not gpu"                       # skip GPUDirect tests
pytest -m integration                     # only real-hardware tests

Markers: integration (needs an RDMA NIC), gpu (needs CUDA + torch). Set RDMA4PY_SKIP_HARDWARE_TESTS=1 to force hardware-dependent tests to skip.

License

BSD-3-Clause. See the repository LICENSE.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ibverbs-2026.7.22.tar.gz (354.8 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

ibverbs-2026.7.22-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl (1.1 MB view details)

Uploaded CPython 3.9+manylinux: glibc 2.17+ ARM64manylinux: glibc 2.28+ ARM64

ibverbs-2026.7.22-cp39-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl (1.1 MB view details)

Uploaded CPython 3.9+manylinux: glibc 2.28+ x86-64manylinux: glibc 2.5+ x86-64

File details

Details for the file ibverbs-2026.7.22.tar.gz.

File metadata

  • Download URL: ibverbs-2026.7.22.tar.gz
  • Upload date:
  • Size: 354.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for ibverbs-2026.7.22.tar.gz
Algorithm Hash digest
SHA256 0420f1395b8fac8fdf8b208fd3d6bd3f1d6c52a3cd92a04bbd988a712ba5bd93
MD5 40ed21507962a6aaa01f60fd40975f44
BLAKE2b-256 39fb3c6a628fcc70fdb6e4412ab83c14a82c42535adb66b6111adf7881ffa5ce

See more details on using hashes here.

Provenance

The following attestation bundles were made for ibverbs-2026.7.22.tar.gz:

Publisher: publish.yml on d4l3k/rdma4py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ibverbs-2026.7.22-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for ibverbs-2026.7.22-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 2c14d89c73f070d93d1d8cb9d686bfb608b4724d45d870a75b13580650245f60
MD5 8590520519691722a5d4fa8c9d122985
BLAKE2b-256 380861028f89b00501160e1da3ddce55ee6f6f5969551c4f791963da52672ac8

See more details on using hashes here.

Provenance

The following attestation bundles were made for ibverbs-2026.7.22-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl:

Publisher: publish.yml on d4l3k/rdma4py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ibverbs-2026.7.22-cp39-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl.

File metadata

File hashes

Hashes for ibverbs-2026.7.22-cp39-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl
Algorithm Hash digest
SHA256 f2d9eea64efdf615ee472d6852c6b461500cfa997c87a9518e87ed9e42b9ee24
MD5 60eade002bc9786d7400099ee922a83b
BLAKE2b-256 9b316d227598d7da85c037d4965afee1caeeb63c9682b109441083cccc4c6990

See more details on using hashes here.

Provenance

The following attestation bundles were made for ibverbs-2026.7.22-cp39-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl:

Publisher: publish.yml on d4l3k/rdma4py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

2026.9.6

3 files

2026.9.5

3 files

2026.9.4

3 files

2026.9.3

3 files

2026.9.2

3 files

2026.9.1

3 files

2026.8.31

3 files

2026.8.30

3 files

2026.8.29

3 files

2026.8.28

3 files

2026.8.27

3 files

2026.8.26

3 files

2026.8.25

3 files

2026.8.24

3 files

2026.8.23

3 files

2026.8.22

3 files

2026.8.21

3 files

2026.8.20

3 files

2026.8.19

3 files

2026.8.18

3 files

2026.8.17

3 files

2026.8.16

3 files

2026.8.15

3 files

2026.8.14

3 files

2026.8.13

3 files

2026.8.12

3 files

2026.8.11

3 files

2026.8.10

3 files

2026.8.9

3 files

2026.8.8

3 files

2026.8.7

3 files

2026.8.6

3 files

2026.8.5

3 files

2026.8.4

3 files

2026.8.3

3 files

2026.8.2

3 files

2026.8.1

3 files

2026.7.30

3 files

2026.7.29

3 files

2026.7.28

3 files

2026.7.27

3 files

2026.7.26

3 files

2026.7.25

3 files

2026.7.24

3 files

2026.7.23

3 files

This release

2026.7.22 This release

3 files

2026.7.21

3 files

2026.7.20

3 files

2026.7.19

3 files

2026.7.18

3 files

2026.7.17

3 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page