EFA API#
Core API#
efa: low-level Pythonic bindings for AWS EFA (SRD RDMA).
Quickstart (SRD is connectionless – no per-QP handshake, just exchange
EndpointInfo once):
import efa
dev = efa.get_efa_device_list()[0]
ctx = dev.open()
pd = ctx.alloc_pd()
cq = ctx.create_cq(256)
qp = pd.create_qp(efa.QPInitAttr(send_cq=cq, recv_cq=cq)).prepare(qkey=0x1234)
info = efa.local_endpoint_info(qp, qkey=0x1234)
# ... exchange info.to_bytes() with the peer out-of-band ...
peer = efa.EndpointInfo.from_bytes(remote_bytes).peer(pd)
mr = efa.reg_tensor(pd, tensor, efa.AccessFlags.LOCAL_WRITE)
qp.post_send(efa.SendWR(sg_list=[mr.sge()], opcode=efa.WROpcode.SEND,
send_flags=efa.SendFlags.SIGNALED, dest=peer))
The compiled fast paths live in efa._efa; enums in efa.enums;
address-exchange and tensor helpers in efa.helpers.
- class efa.AH#
Bases:
objectAn address handle naming a remote EFA device (by GID).
- ahn#
int
The EFA address handle number (
efadv_query_ah).- Type:
AH.ahn
- close(self)#
Destroy this address handle.
- pd#
- class efa.CQ#
Bases:
_CQBaseA classic completion queue (
ibv_cq).- close(self)#
Destroy this classic completion queue.
- class efa.CQAttr#
Bases:
objectAn EFA completion queue’s direct layout from
efadv_query_cq.- buffer_addr#
- doorbell_addr#
- entry_size#
- num_entries#
- class efa.CQEx#
Bases:
_CQBaseAn extended EFA completion queue (
efadv_create_cq).Functionally a
CQ, plus optional sender-GID reporting (sgid=True): SRD/UD receivers can identify previously unknown peers straight from the completion (seeWC.sgid).- close(self)#
Destroy this extended completion queue.
- poll(self, int num_entries) list#
Poll up to
num_entriescompletions; return a list ofWC.- Return type:
- sgid_enabled#
bool
Whether polled completions request sender GID metadata.
- Type:
CQEx.sgid_enabled
- unsolicited_enabled#
bool
Whether unsolicited-write completion metadata is enabled.
- Type:
CQEx.unsolicited_enabled
- class efa.MR#
Bases:
objectA registered memory region (
ibv_mr).- addr#
int
Return the registered region’s starting virtual address.
- Type:
MR.addr
- close(self)#
Deregister this memory region.
- closed#
bool
Whether this memory region has been deregistered.
- Type:
MR.closed
- handle#
int
Return the provider memory-region handle.
- Type:
MR.handle
- length#
int
Return the registered length in bytes.
- Type:
MR.length
- lkey#
int
Return the local key used by this process’s QPs.
- Type:
MR.lkey
- owner#
- pd#
- rkey#
int
Return the key that authorizes remote access.
- Type:
MR.rkey
- class efa.PD#
Bases:
objectA protection domain (
ibv_pd).- close(self)#
Deallocate the protection domain when it has no open children.
- context#
- create_ah(self, addr, int sgid_index=0, int port_num=1) 'AH'#
Create an address handle for a remote EFA device.
addrmay be anAHAttr, aGid, or 16 raw GID bytes.- Return type:
- create_qp(self, init_attr) 'QP'#
Create an SRD (default) or UD queue pair.
SRD QPs go through
efadv_create_qp_ex; UD QPs throughibv_create_qp_ex. Both are created with the extended send-ops work-request API enabled (seeQPInitAttr).- Return type:
- reg_dmabuf_mr(self, offset, length, iova, int fd, int access) 'MR'#
Register a dma-buf backed region (modern GPUDirect path).
- Return type:
- class efa.QP#
Bases:
objectAn EFA queue pair (SRD or UD).
Sends go through the extended work-request API under the hood, so every supported opcode, including RDMA read/write on SRD, which the classic
ibv_post_sendcannot express on this provider, posts uniformly viapost_send().- close(self)#
Destroy this queue pair.
- modify(self, int attr_mask, **fields)#
Low-level
ibv_modify_qp.attr_maskis an ORedQPAttrMask. Scalar attributes are passed as keywords (e.g.qp_state=,qkey=).
- pd#
- post_send(self, wrs)#
Post one or more
SendWRas a single batch.All work requests are queued between
wr_start/wr_complete, so either the whole batch is submitted or none of it is.EFA requires every send WR to carry
SIGNALED(or the QP must be created withsq_sig_all=True); an unsignaled WR fails the batch with EINVAL.
- prepare(self, qkey, int port=1, psn=0, rnr_retry=None)#
Drive RESET -> INIT -> RTR -> RTS in one call.
SRD/UD are connectionless, so a QP is fully usable after this without any remote information; destinations are named per-send.
qkey,port,psn, andrnr_retryare forwarded to the corresponding state-transition methods.
- qp_num#
int
Return the provider-assigned queue-pair number.
- Type:
QP.qp_num
- qp_type#
- query(self)#
Return
(attrs, cap)for the queue pair as plain dict + QPCap.
- recv_cq#
- send_cq#
- send_ops_flags#
- state#
int
The queue pair’s current state (authoritative, via query).
- Type:
QP.state
- to_init(self, qkey, int port=1, int pkey_index=0)#
Transition RESET -> INIT.
qkeyauthorizes incoming datagrams;portselects the local physical port andpkey_indexselects its partition-key entry.
- to_rtr(self)#
Transition INIT -> RTR (connectionless: no remote info needed).
- class efa.AHAttr(dgid=None, sgid_index=0, port_num=1, hop_limit=1, traffic_class=0, flow_label=0, is_global=1)#
Bases:
objectAddress-handle attributes.
EFA addresses are GIDs: only
dgid(the remote device’s GID),sgid_indexandport_nummatter; the rest exists for parity with generic verbs.- Parameters:
dgid – Remote 16-byte GID. Defaults to all zeroes.
sgid_index – Local source-GID table index.
port_num – Local physical port number.
hop_limit – Global-route hop limit.
traffic_class – Global-route traffic class.
flow_label – Global-route flow label.
is_global – Whether to populate the global route header.
- dgid#
bytes
- Type:
dgid
- flow_label#
‘uint32_t’
- Type:
flow_label
- hop_limit#
‘uint8_t’
- Type:
hop_limit
- is_global#
‘uint8_t’
- Type:
is_global
- port_num#
‘uint8_t’
- Type:
port_num
- sgid_index#
‘uint8_t’
- Type:
sgid_index
- traffic_class#
‘uint8_t’
- Type:
traffic_class
- class efa.AsyncEvent#
Bases:
objectAn asynchronous device event from
Context.get_async_event().- event_type#
- event_type_str#
str
Return the human-readable asynchronous event type.
- Type:
AsyncEvent.event_type_str
- class efa.CompChannel#
Bases:
objectA completion event channel (
ibv_comp_channel).- close(self)#
Destroy the completion channel after its CQs are closed.
- context#
- fd#
int
Return the completion channel’s pollable file descriptor.
- Type:
CompChannel.fd
- exception efa.CompletionError(wc)#
Bases:
EfaErrorRaised by
WC.raise_for_status()for a failed completion.
- class efa.Context#
Bases:
objectAn open device context (
ibv_context).- ack_async_event(self, AsyncEvent ev)#
Acknowledge an event returned by
get_async_event().
- async_fd#
int
Return the file descriptor used for asynchronous device events.
- Type:
Context.async_fd
- close(self)#
Close the device context after all child resources are closed.
- create_comp_channel(self) 'CompChannel'#
Create a completion event channel owned by this context.
- Return type:
- create_cq(self, int cqe, channel=None, int comp_vector=0) 'CQ'#
Create a classic completion queue (
ibv_create_cq).cqeis the requested minimum capacity.channeloptionally enables event notification, andcomp_vectorselects its interrupt vector from0throughnum_comp_vectors - 1.- Return type:
- create_cq_ex(self, int cqe, channel=None, int comp_vector=0, wc_flags=None, bool sgid=False, bool unsolicited=False) 'CQEx'#
Create an extended EFA completion queue (
efadv_create_cq).sgid=Truerequests sender-GID reporting on receive completions (needsCQ_WITH_SGID); the GID shows up asWC.sgidfor peers not matched by a local AH.unsolicited=Truerequests an indicator for unsolicited write-with-immediate receive completions (needsUNSOLICITED_WRITE_RECV).cqe,channel, andcomp_vectorhave the same meaning as increate_cq().wc_flagsis an ORedCreateCQWCFlagsmask and defaults toSTANDARD.- Return type:
- get_async_event(self) 'AsyncEvent'#
Block until an asynchronous device event is available.
- Return type:
- name#
- num_comp_vectors#
int
Return the number of completion interrupt vectors.
- Type:
Context.num_comp_vectors
- query_device(self) DeviceAttr#
Query generic verbs capabilities for this device.
- Return type:
- query_efa_device(self) EfaDeviceAttr#
EFA capabilities (
efadv_query_device).Raises
EfaErrorif the device is not an EFA device.- Return type:
- class efa.Device(str name, uint64_t guid)#
Bases:
objectAn RDMA device discovered by
get_device_list().- guid#
- name#
- class efa.DeviceAttr#
Bases:
objectGeneric verbs device capabilities from
Context.query_device().- fw_ver#
- hw_ver#
- max_ah#
- max_cq#
- max_cqe#
- max_mr#
- max_mr_size#
- max_pd#
- max_pkeys#
- max_qp#
- max_qp_wr#
- max_sge#
- node_guid#
- phys_port_cnt#
- sys_image_guid#
- vendor_id#
- vendor_part_id#
- class efa.EfaDeviceAttr#
Bases:
objectEFA-specific capabilities from
Context.query_efa_device().- device_caps#
- inline_buf_size#
- max_rdma_size#
- max_rq_sge#
- max_rq_wr#
- max_sq_sge#
- max_sq_wr#
- exception efa.EfaError(operation, err, detail=None)#
Bases:
OSErrorRaised when a libibverbs/libefa call fails.
Subclasses
OSError, so.errnoand.strerrorare populated..operationnames the call that failed.
- class efa.Gid(bytes raw)#
Bases:
objectA 16-byte GID (the EFA device address).
- interface_id#
int
Return the least-significant 64 bits in network byte order.
- Type:
Gid.interface_id
- raw#
- subnet_prefix#
int
Return the most-significant 64 bits in network byte order.
- Type:
Gid.subnet_prefix
- class efa.MRAttr#
Bases:
objectEFA MR attributes from
MR.query_efa()(efadv_query_mr).- ic_id_validity#
- rdma_read_ic_id#
- rdma_recv_ic_id#
- recv_ic_id#
- class efa.PortAttr#
Bases:
objectPort attributes from
Context.query_port().max_msg_szis the SEND size limit; RDMA read/write are limited byEfaDeviceAttr.max_rdma_sizeinstead.- active_mtu#
- active_speed#
- active_width#
- gid_tbl_len#
- lid#
- link_layer#
- max_msg_sz#
- max_mtu#
- pkey_tbl_len#
- port_cap_flags#
- state#
- class efa.QPCap#
Bases:
objectQueue-pair capacity limits.
- max_inline_data#
- max_recv_sge#
- max_recv_wr#
- max_send_sge#
- max_send_wr#
- class efa.QPInitAttr(send_cq, recv_cq, qp_type=None, max_send_wr=128, max_recv_wr=128, max_send_sge=1, max_recv_sge=1, max_inline_data=0, sq_sig_all=False, send_ops_flags=None, sl=0, unsolicited_write_recv=False)#
Bases:
objectParameters for
PD.create_qp().- Parameters:
send_cq – Completion queue for send work requests.
recv_cq – Completion queue for receive work requests.
qp_type –
SRD(default) orUD.max_send_wr – Requested maximum outstanding send work requests.
max_recv_wr – Requested maximum posted receive work requests.
max_send_sge – Requested SGE limit for each send request.
max_recv_sge – Requested SGE limit for each receive request.
max_inline_data – Requested maximum inline payload in bytes.
sq_sig_all – Make every send produce a completion, even without the
SIGNALEDflag. EFA requires one of these two signaling mechanisms for every send.send_ops_flags – Enabled
QPExSendOpsFlags. The default enables every operation supported by the QP type. Pass an explicit mask on devices without RDMA read/write support.sl – EFA service level used when creating an SRD QP.
unsolicited_write_recv – Accept RDMA-write-with-immediate without a posted receive. Requires the matching EFA device capability and an extended CQ created with
unsolicited=True.
- class efa.RecvWR(wr_id=0, sg_list=None)#
Bases:
objectA receive work request.
- Parameters:
wr_id – Application-defined value returned in the completion.
sg_list – Local
SGEobjects that receive the payload.
- sg_list#
list
- Type:
sg_list
- wr_id#
‘uint64_t’
- Type:
wr_id
- class efa.SendWR(wr_id=0, sg_list=None, opcode=2, send_flags=0, remote_addr=0, rkey=0, imm_data=0, ah=None, remote_qpn=0, remote_qkey=0, dest=None)#
Bases:
objectA send work request.
SRD/UD is connectionless: every send names its destination. Set either
dest=(anything with.ah,.qp_numand.qkeyattributes, e.g.efa.helpers.Peer) or the explicitah/remote_qpn/remote_qkeytrio.Opcodes: SEND, SEND_WITH_IMM, RDMA_READ, RDMA_WRITE, RDMA_WRITE_WITH_IMM (RDMA opcodes additionally need
remote_addr/rkey).- Parameters:
wr_id – Application-defined value returned in the completion.
sg_list – Local
SGEobjects. Defaults to an empty list.opcode – A
WROpcodevalue; defaults toSEND.send_flags – ORed
SendFlagsvalues. EFA requiresSIGNALEDunless the QP usessq_sig_all=True.remote_addr – Remote virtual address for an RDMA operation.
rkey – Remote memory key for an RDMA operation.
imm_data – Immediate data for an opcode ending in
WITH_IMM.ah – Explicit destination address handle.
remote_qpn – Explicit destination queue-pair number.
remote_qkey – Explicit destination qkey.
dest – Convenience object supplying
ah,qp_num, andqkey; mutually exclusive with the explicit destination fields.
- ah#
object
- Type:
ah
- imm_data#
‘uint32_t’
- Type:
imm_data
- opcode#
‘int’
- Type:
opcode
- remote_addr#
‘uint64_t’
- Type:
remote_addr
- remote_qkey#
‘uint32_t’
- Type:
remote_qkey
- remote_qpn#
‘uint32_t’
- Type:
remote_qpn
- rkey#
‘uint32_t’
- Type:
rkey
- send_flags#
‘unsigned int’
- Type:
send_flags
- sg_list#
list
- Type:
sg_list
- wr_id#
‘uint64_t’
- Type:
wr_id
- class efa.SGE(target, length, lkey=0, offset=0)#
Bases:
objectA scatter/gather entry.
SGE(target, length, lkey=0, offset=0)wheretargetis either anMR(lkey/addrderived from it) or an integer address.- addr#
- length#
- lkey#
- owner#
- class efa.WC#
Bases:
objectA work completion returned by
CQ.poll()/CQEx.poll().For completions from a
CQExcreated withsgid=True,sgidcarries the sender’s GID on receive completions from peers not covered by a local AH (elseNone).- byte_len#
- imm_data#
- is_success#
bool
Whether the work request completed successfully.
- Type:
WC.is_success
- opcode#
- qp_num#
- raise_for_status(self)#
Raise
CompletionErrorif this completion did not succeed.
- sgid#
- src_qp#
- status#
- status_str#
str
Return the provider’s human-readable completion status.
- Type:
WC.status_str
- unsolicited#
- vendor_err#
- wc_flags#
- wr_id#
- class efa.WQAttr#
Bases:
objectA work queue’s layout from
QP.query_wqs()(efadv_query_qp_wqs).- buffer_addr#
- doorbell_addr#
- entry_size#
- max_batch#
- num_entries#
- efa.get_device_list() list#
Return every RDMA
Deviceon this host (EFA or not).Use
get_efa_device_list()to keep only EFA devices.- Return type:
- efa.get_efa_device_list() list#
Return the
Devicelist filtered to EFA devices.Each device is briefly opened and probed with
efadv_query_device.- Return type:
- class efa.AccessFlags(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)#
Bases:
IntFlagMemory-region access permissions (
IBV_ACCESS_*).- LOCAL_WRITE = 1#
Permit the local HCA to write the registered memory.
- REMOTE_WRITE = 2#
Permit a remote peer to write the region; also requires
LOCAL_WRITE.
- REMOTE_READ = 4#
Permit a remote peer to read the region.
- RELAXED_ORDERING = 1048576#
Allow relaxed inbound write ordering for higher performance.
- class efa.CreateCQWCFlags(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)#
Bases:
IntFlagExtended-CQ per-completion fields (
IBV_WC_EX_WITH_*).STANDARDmatches what classicibv_poll_cqreports and is the default forcreate_cq_ex().- BYTE_LEN = 1#
Request the completed byte count.
- IMM = 2#
Request immediate data.
- QP_NUM = 4#
Request the local queue-pair number.
- SRC_QP = 8#
Request the source queue-pair number.
- SLID = 16#
Request the source LID.
- SL = 32#
Request the service level.
- DLID_PATH_BITS = 64#
Request destination LID path bits.
- STANDARD = 127#
Request every field reported by a classic completion queue.
- class efa.EfaDeviceCaps(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)#
Bases:
IntFlagEFA device capability bits (
EFADV_DEVICE_ATTR_CAPS_*).Test against
device_caps.- RDMA_READ = 1#
The provider supports SRD RDMA Read.
- RNR_RETRY = 2#
The provider supports configurable RNR retry.
- CQ_WITH_SGID = 4#
Extended completion queues can report sender GIDs.
- RDMA_WRITE = 8#
The provider supports SRD RDMA Write.
- UNSOLICITED_WRITE_RECV = 16#
QPs can receive unsolicited RDMA Write with Immediate.
- CQ_WITH_EXT_MEM_DMABUF = 32#
Extended completion-queue memory can be supplied through dma-buf.
- class efa.MTU(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)#
Bases:
IntEnumPath MTU (
IBV_MTU_*).- MTU_256 = 1#
- MTU_512 = 2#
- MTU_1024 = 3#
- MTU_2048 = 4#
- MTU_4096 = 5#
- class efa.PortState(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)#
Bases:
IntEnumPort state (
IBV_PORT_*).- NOP = 0#
- DOWN = 1#
- INIT = 2#
- ARMED = 3#
- ACTIVE = 4#
- ACTIVE_DEFER = 5#
- class efa.QPAttrMask(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)#
Bases:
IntFlagBitmask selecting which fields
modify_qpapplies (IBV_QP_*).- STATE = 1#
Apply
qp_state.
- CUR_STATE = 2#
Apply
cur_qp_stateas a transition precondition.
- PKEY_INDEX = 16#
Apply the partition-key table index.
- PORT = 32#
Apply the local physical port.
- QKEY = 64#
Apply the datagram queue key.
- RNR_RETRY = 2048#
Apply the receiver-not-ready retry count.
- RQ_PSN = 4096#
Apply the receive packet sequence number.
- SQ_PSN = 65536#
Apply the send packet sequence number.
- class efa.QPExSendOpsFlags(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)#
Bases:
IntFlagExtended-QP send operations (
IBV_QP_EX_WITH_*).Passed as
QPInitAttr.send_ops_flags; the created QP can only post the opcodes enabled here.- RDMA_WRITE = 1#
Enable RDMA Write work requests.
- RDMA_WRITE_WITH_IMM = 2#
Enable RDMA Write with Immediate work requests.
- SEND = 4#
Enable Send work requests.
- SEND_WITH_IMM = 8#
Enable Send with Immediate work requests.
- RDMA_READ = 16#
Enable RDMA Read work requests.
- class efa.QPState(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)#
Bases:
IntEnumQueue-pair state (
IBV_QPS_*).- RESET = 0#
- INIT = 1#
- RTR = 2#
- RTS = 3#
- SQD = 4#
- SQE = 5#
- ERR = 6#
- UNKNOWN = 7#
- class efa.QPType(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)#
Bases:
IntEnumEFA queue-pair type.
SRD(Scalable Reliable Datagram – reliable, connectionless, out-of-order; EFA’s native transport) orUD(unreliable datagram). SRD maps ontoIBV_QPT_DRIVERand is created through the EFA provider.- UD = 4#
- SRD = 255#
- class efa.SendFlags(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)#
Bases:
IntFlagSend work-request flags (
IBV_SEND_*).- FENCE = 1#
Fence this request behind earlier RDMA Read or atomic operations.
- SIGNALED = 2#
Generate a send completion for this request.
- SOLICITED = 4#
Request a solicited receive event at the peer.
- INLINE = 8#
Copy the payload into the work request instead of retaining its SGEs.
- class efa.WCFlags(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)#
Bases:
IntFlagWork-completion flags (
IBV_WC_*bit flags).- GRH = 1#
A global route header precedes the received payload.
- WITH_IMM = 2#
The completion contains valid immediate data.
- class efa.WCOpcode(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)#
Bases:
IntEnumWork-completion opcode (
IBV_WC_*).- SEND = 0#
- RDMA_WRITE = 1#
- RDMA_READ = 2#
- RECV = 128#
- RECV_RDMA_WITH_IMM = 129#
- class efa.WCStatus(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)#
Bases:
IntEnumWork-completion status (
IBV_WC_*).- SUCCESS = 0#
- LOC_LEN_ERR = 1#
- LOC_QP_OP_ERR = 2#
- LOC_EEC_OP_ERR = 3#
- LOC_PROT_ERR = 4#
- WR_FLUSH_ERR = 5#
- MW_BIND_ERR = 6#
- BAD_RESP_ERR = 7#
- LOC_ACCESS_ERR = 8#
- REM_INV_REQ_ERR = 9#
- REM_ACCESS_ERR = 10#
- REM_OP_ERR = 11#
- RETRY_EXC_ERR = 12#
- RNR_RETRY_EXC_ERR = 13#
- LOC_RDD_VIOL_ERR = 14#
- REM_INV_RD_REQ_ERR = 15#
- REM_ABORT_ERR = 16#
- INV_EECN_ERR = 17#
- INV_EEC_STATE_ERR = 18#
- FATAL_ERR = 19#
- RESP_TIMEOUT_ERR = 20#
- GENERAL_ERR = 21#
- class efa.WROpcode(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)#
Bases:
IntEnumSend work-request opcode (
IBV_WR_*, the subset EFA supports).- RDMA_WRITE = 0#
- RDMA_WRITE_WITH_IMM = 1#
- SEND = 2#
- SEND_WITH_IMM = 3#
- RDMA_READ = 4#
- class efa.EndpointInfo(gid, qp_num, qkey)#
Bases:
objectThe minimum a peer needs to send to an SRD/UD queue pair.
Exchange this out-of-band (e.g. over a TCP socket or a distributed key-value store) during setup.
to_bytes()/from_bytes()give a fixed 24-byte wire layout so both ends agree regardless of platform endianness.
- class efa.Peer(ah, qp_num, qkey)#
Bases:
objectA resolved remote endpoint: an AH plus QP number and qkey.
Pass as
dest=toSendWR. Owns the AH;close()(or use as a context manager) destroys it.- close()#
Destroy the owned address handle, if it is still open.
- Return type:
None
- efa.local_endpoint_info(qp, qkey, *, gid=None, gid_index=0, port=1)#
Build an
EndpointInfodescribingqpfor sending to a peer.qkeymust match what the QP was prepared with. The GID is queried from the QP’s device unless passed explicitly.gid_indexandportselect that query whengidis omitted.- Parameters:
- Return type:
- efa.read_wrs(mr, dest, remote_addr, rkey, *, length=None, offset=0, chunk=1073741824, wr_id=0)#
Build the work requests for an RDMA read into
mr.destnames the remote EFA peer;remote_addrandrkeyselect its memory region.lengthdefaults to the local MR remainder afteroffset.chunkis the maximum bytes per WR, andwr_idseeds the sequential request identifiers.
- efa.reg_tensor(pd, tensor, access)#
Register a host (CPU) tensor’s memory as an MR via
reg_mr.Convenience for a contiguous torch CPU tensor or numpy array. For CUDA tensors use
efa.cuda.register_tensor()(dma-buf/GPUDirect) instead.pdis the owning protection domain andaccessis an ORedAccessFlagsmask.
- efa.tensor_addr_len(tensor)#
Return
(addr, nbytes)for a tensor-like object (torch or numpy).Works with a torch tensor (
data_ptr()+numel()*element_size()) or a numpy array (ctypes.data+nbytes). No import of either library is required; the object is duck-typed.
- efa.write_wrs(mr, dest, remote_addr, rkey, *, length=None, offset=0, chunk=1073741824, wr_id=0)#
Build the
SendWRlist for a (possibly huge) RDMA write.EFA caps a single RDMA operation at
max_rdma_size(1 GiB on current hardware), so a tensor-sized transfer may need several work requests. This slicesmr[offset:offset+length]intochunk-sized writes targetingremote_addrat matching offsets. Every WR is SIGNALED (an EFA requirement), so expectlen(wrs)completions; they complete in posting order, and SRD completes a WR only once it is fully delivered.mrmay be anMRor a GpuMR-like object exposingaddr/length/lkey. Returns a list of SendWRs to pass topost_send();wr_idnumbers them sequentially.destnames the remote EFA peer;remote_addrandrkeyselect its memory region.lengthdefaults to the local MR remainder afteroffset.chunkis the maximum bytes per WR.
Helpers#
Thin, optional helpers for the common EFA/SRD workflow.
These build on the raw verbs in efa._efa. The raw QP.modify /
QP.to_init / QP.to_rtr / QP.to_rts remain available for callers
that want full control.
SRD is connectionless: unlike RC there is no per-QP connection handshake.
Bootstrap is a one-shot exchange of EndpointInfo (GID + QP number +
qkey) out-of-band, e.g. over a TCP socket or a torch distributed store,
after which EndpointInfo.peer() gives a Peer that any number
of sends can target.
- class efa.helpers.EndpointInfo(gid, qp_num, qkey)#
Bases:
objectThe minimum a peer needs to send to an SRD/UD queue pair.
Exchange this out-of-band (e.g. over a TCP socket or a distributed key-value store) during setup.
to_bytes()/from_bytes()give a fixed 24-byte wire layout so both ends agree regardless of platform endianness.
- class efa.helpers.Peer(ah, qp_num, qkey)#
Bases:
objectA resolved remote endpoint: an AH plus QP number and qkey.
Pass as
dest=toSendWR. Owns the AH;close()(or use as a context manager) destroys it.- close()#
Destroy the owned address handle, if it is still open.
- Return type:
None
- efa.helpers.local_endpoint_info(qp, qkey, *, gid=None, gid_index=0, port=1)#
Build an
EndpointInfodescribingqpfor sending to a peer.qkeymust match what the QP was prepared with. The GID is queried from the QP’s device unless passed explicitly.gid_indexandportselect that query whengidis omitted.- Parameters:
- Return type:
- efa.helpers.tensor_addr_len(tensor)#
Return
(addr, nbytes)for a tensor-like object (torch or numpy).Works with a torch tensor (
data_ptr()+numel()*element_size()) or a numpy array (ctypes.data+nbytes). No import of either library is required; the object is duck-typed.
- efa.helpers.reg_tensor(pd, tensor, access)#
Register a host (CPU) tensor’s memory as an MR via
reg_mr.Convenience for a contiguous torch CPU tensor or numpy array. For CUDA tensors use
efa.cuda.register_tensor()(dma-buf/GPUDirect) instead.pdis the owning protection domain andaccessis an ORedAccessFlagsmask.
- efa.helpers.write_wrs(mr, dest, remote_addr, rkey, *, length=None, offset=0, chunk=1073741824, wr_id=0)#
Build the
SendWRlist for a (possibly huge) RDMA write.EFA caps a single RDMA operation at
max_rdma_size(1 GiB on current hardware), so a tensor-sized transfer may need several work requests. This slicesmr[offset:offset+length]intochunk-sized writes targetingremote_addrat matching offsets. Every WR is SIGNALED (an EFA requirement), so expectlen(wrs)completions; they complete in posting order, and SRD completes a WR only once it is fully delivered.mrmay be anMRor a GpuMR-like object exposingaddr/length/lkey. Returns a list of SendWRs to pass topost_send();wr_idnumbers them sequentially.destnames the remote EFA peer;remote_addrandrkeyselect its memory region.lengthdefaults to the local MR remainder afteroffset.chunkis the maximum bytes per WR.
- efa.helpers.read_wrs(mr, dest, remote_addr, rkey, *, length=None, offset=0, chunk=1073741824, wr_id=0)#
Build the work requests for an RDMA read into
mr.destnames the remote EFA peer;remote_addrandrkeyselect its memory region.lengthdefaults to the local MR remainder afteroffset.chunkis the maximum bytes per WR, andwr_idseeds the sequential request identifiers.
CUDA#
Optional CUDA GPUDirect helpers for registering GPU tensors as memory regions.
This module lazily dlopen``s ``libcuda and imports no torch and links
no CUDA at build time, so it adds no required dependency. It is duck-typed:
anything exposing data_ptr() (e.g. a torch CUDA tensor) works.
For torch, allocate with the VMM allocator so the memory can be exported as a
dma-buf fd (the fd libibverbs needs for ibv_reg_dmabuf_mr):
PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True
Typical use:
import efa, efa.cuda, torch
t = torch.zeros(1 << 20, dtype=torch.uint8, device="cuda")
gmr = efa.cuda.register_tensor(pd, t, efa.AccessFlags.LOCAL_WRITE)
qp.post_send(efa.SendWR(sg_list=[gmr.sge()], dest=peer, ...))
Before the NIC reads a tensor, synchronize the CUDA stream that produced it.
After an inbound completion, call flush_gpudirect_writes() before CUDA
work consumes the destination.
- class efa.cuda.GpuMR(mr, addr, length, tensor=None)#
Bases:
objectA registered GPU memory region plus the info needed to address it.
ibv_mr.addris not meaningful for dma-buf MRs, so this wraps the real device virtual address. Usesge()for the local scatter/gather list andaddr/rkeyfor the remote side of an RDMA op.- property tensor#
The tensor retained as this registration’s allocation owner.
- sge(length=None, offset=0)#
Build an SGE for a byte range of this GPU memory region.
- close()#
Deregister the memory region and release the retained tensor.
- efa.cuda.dmabuf_fd(ptr, length)#
Export a dma-buf fd for the device VA range
[ptr, ptr+length).ptrandlengthmust be page-aligned (register_tensor()handles alignment). The caller owns and mustos.closethe returned fd.
- efa.cuda.flush_gpudirect_writes(*, all_devices=False)#
Make completed inbound GPUDirect RDMA writes visible to CUDA.
Call this after the relevant receive/completion or application-level remote-write notification, before launching CUDA work that consumes the destination tensor. The current thread must have the destination tensor’s CUDA context active. By default CUDA flushes writes only to the owning device; set
all_devices=Trueto flush visibility to every GPU in the current context’s scope.- Parameters:
all_devices (bool) –
- Return type:
None
- efa.cuda.tensor_ptr_len(tensor)#
Return
(device_addr, nbytes)for a tensor-like object.
- efa.cuda.register_tensor(pd, tensor, access)#
Register a CUDA
tensorfor RDMA and return aGpuMR.Prefers the dma-buf path (no kernel module needed) and transparently handles page alignment. Falls back to the raw
reg_mr(nvidia_peermem) path when dma-buf export or registration is unavailable. The returned object retainstensorso its allocation cannot be recycled while the MR is registered.pdis the owning protection domain andaccessis an ORedAccessFlagsmask.- Return type:
Enums#
Pythonic enums mirroring the libibverbs / libefa ABI constants.
These values are part of the stable rdma-core ABI. They are declared here as
enum.IntEnum / enum.IntFlag so they interoperate with plain
ints everywhere the low-level API accepts a flag or code.
- class efa.enums.AccessFlags(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)#
Bases:
IntFlagMemory-region access permissions (
IBV_ACCESS_*).- LOCAL_WRITE = 1#
Permit the local HCA to write the registered memory.
- REMOTE_WRITE = 2#
Permit a remote peer to write the region; also requires
LOCAL_WRITE.
- REMOTE_READ = 4#
Permit a remote peer to read the region.
- RELAXED_ORDERING = 1048576#
Allow relaxed inbound write ordering for higher performance.
- class efa.enums.QPType(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)#
Bases:
IntEnumEFA queue-pair type.
SRD(Scalable Reliable Datagram – reliable, connectionless, out-of-order; EFA’s native transport) orUD(unreliable datagram). SRD maps ontoIBV_QPT_DRIVERand is created through the EFA provider.- UD = 4#
- SRD = 255#
- class efa.enums.QPState(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)#
Bases:
IntEnumQueue-pair state (
IBV_QPS_*).- RESET = 0#
- INIT = 1#
- RTR = 2#
- RTS = 3#
- SQD = 4#
- SQE = 5#
- ERR = 6#
- UNKNOWN = 7#
- class efa.enums.QPAttrMask(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)#
Bases:
IntFlagBitmask selecting which fields
modify_qpapplies (IBV_QP_*).- STATE = 1#
Apply
qp_state.
- CUR_STATE = 2#
Apply
cur_qp_stateas a transition precondition.
- PKEY_INDEX = 16#
Apply the partition-key table index.
- PORT = 32#
Apply the local physical port.
- QKEY = 64#
Apply the datagram queue key.
- RNR_RETRY = 2048#
Apply the receiver-not-ready retry count.
- RQ_PSN = 4096#
Apply the receive packet sequence number.
- SQ_PSN = 65536#
Apply the send packet sequence number.
- class efa.enums.QPExSendOpsFlags(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)#
Bases:
IntFlagExtended-QP send operations (
IBV_QP_EX_WITH_*).Passed as
QPInitAttr.send_ops_flags; the created QP can only post the opcodes enabled here.- RDMA_WRITE = 1#
Enable RDMA Write work requests.
- RDMA_WRITE_WITH_IMM = 2#
Enable RDMA Write with Immediate work requests.
- SEND = 4#
Enable Send work requests.
- SEND_WITH_IMM = 8#
Enable Send with Immediate work requests.
- RDMA_READ = 16#
Enable RDMA Read work requests.
- class efa.enums.WROpcode(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)#
Bases:
IntEnumSend work-request opcode (
IBV_WR_*, the subset EFA supports).- RDMA_WRITE = 0#
- RDMA_WRITE_WITH_IMM = 1#
- SEND = 2#
- SEND_WITH_IMM = 3#
- RDMA_READ = 4#
- class efa.enums.SendFlags(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)#
Bases:
IntFlagSend work-request flags (
IBV_SEND_*).- FENCE = 1#
Fence this request behind earlier RDMA Read or atomic operations.
- SIGNALED = 2#
Generate a send completion for this request.
- SOLICITED = 4#
Request a solicited receive event at the peer.
- INLINE = 8#
Copy the payload into the work request instead of retaining its SGEs.
- class efa.enums.WCStatus(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)#
Bases:
IntEnumWork-completion status (
IBV_WC_*).- SUCCESS = 0#
- LOC_LEN_ERR = 1#
- LOC_QP_OP_ERR = 2#
- LOC_EEC_OP_ERR = 3#
- LOC_PROT_ERR = 4#
- WR_FLUSH_ERR = 5#
- MW_BIND_ERR = 6#
- BAD_RESP_ERR = 7#
- LOC_ACCESS_ERR = 8#
- REM_INV_REQ_ERR = 9#
- REM_ACCESS_ERR = 10#
- REM_OP_ERR = 11#
- RETRY_EXC_ERR = 12#
- RNR_RETRY_EXC_ERR = 13#
- LOC_RDD_VIOL_ERR = 14#
- REM_INV_RD_REQ_ERR = 15#
- REM_ABORT_ERR = 16#
- INV_EECN_ERR = 17#
- INV_EEC_STATE_ERR = 18#
- FATAL_ERR = 19#
- RESP_TIMEOUT_ERR = 20#
- GENERAL_ERR = 21#
- class efa.enums.WCOpcode(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)#
Bases:
IntEnumWork-completion opcode (
IBV_WC_*).- SEND = 0#
- RDMA_WRITE = 1#
- RDMA_READ = 2#
- RECV = 128#
- RECV_RDMA_WITH_IMM = 129#
- class efa.enums.WCFlags(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)#
Bases:
IntFlagWork-completion flags (
IBV_WC_*bit flags).- GRH = 1#
A global route header precedes the received payload.
- WITH_IMM = 2#
The completion contains valid immediate data.
- class efa.enums.CreateCQWCFlags(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)#
Bases:
IntFlagExtended-CQ per-completion fields (
IBV_WC_EX_WITH_*).STANDARDmatches what classicibv_poll_cqreports and is the default forcreate_cq_ex().- BYTE_LEN = 1#
Request the completed byte count.
- IMM = 2#
Request immediate data.
- QP_NUM = 4#
Request the local queue-pair number.
- SRC_QP = 8#
Request the source queue-pair number.
- SLID = 16#
Request the source LID.
- SL = 32#
Request the service level.
- DLID_PATH_BITS = 64#
Request destination LID path bits.
- STANDARD = 127#
Request every field reported by a classic completion queue.
- class efa.enums.EfaDeviceCaps(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)#
Bases:
IntFlagEFA device capability bits (
EFADV_DEVICE_ATTR_CAPS_*).Test against
device_caps.- RDMA_READ = 1#
The provider supports SRD RDMA Read.
- RNR_RETRY = 2#
The provider supports configurable RNR retry.
- CQ_WITH_SGID = 4#
Extended completion queues can report sender GIDs.
- RDMA_WRITE = 8#
The provider supports SRD RDMA Write.
- UNSOLICITED_WRITE_RECV = 16#
QPs can receive unsolicited RDMA Write with Immediate.
- CQ_WITH_EXT_MEM_DMABUF = 32#
Extended completion-queue memory can be supplied through dma-buf.