CVBpy 15.0
cvb/Rdma
1# CVBpy Example Script RDMA for GEV acquisition
2# This enables high data rates with without CPU load
3
4import cvb
5
6from timeit import default_timer as timer
7
8TIMEOUT_MS = 3000
9NUM_ELEMENTS_TO_ACQUIRE = 5000 # number of elements to be acquired
10FEEDBACK_INTERVAL = NUM_ELEMENTS_TO_ACQUIRE / 10 # print progress
11NUM_FLOW_SETS = 10 # number flow sets to announce (usually buffers)
12
13
14# RDMA transfer is part of the socket driver (GevSD) so the filter driver (GevFD) must be ignored.
15devices = cvb.DeviceFactory.discover_from_root(cvb.DiscoverFlags.IgnoreVins | cvb.DiscoverFlags.IgnoreGevFD)
16
17# The following will only work if there is a RDMA capable device connected to an RDMA capable
18# network interface. Usually also a driver that allows user space access is required. See also
19# * Windows: Network Direct Service Provider Interface (NDSPI)
20# * Linux: librdmacm.so and libibverbs.so
21item = devices[0]
22# RDMA must be switched on explicitly otherwise the classic GVSP protocol will be used.
23# This is just a request and may fail silently if RDMA is not supported.
24# To verify that RDMA is supported and switched on you can check
25# the "GevDataStreamingMode" in the TLDevice (cvb.NodeMapID.TLDevice) node map and validate that it is
26# set to "RDMA". The "RDMA" entry is only available if the device is RDMA capable.
27item.set_parameter("UseRdma", "1")
28
29with cvb.DeviceFactory.open(item.access_token, cvb.AcquisitionStack.GenTL) as device:
30 node_map = device.node_maps[cvb.NodeMapID.Device]
31 payload_size = node_map.node("PayloadSize").value
32 # Note that RDMA requires GenDC containers as payload.
33 # The container will automatically be mapped to a composite for
34 # further processing.
35 stream = device.stream(cvb.CompositeStream)
36
37 # The default and minimal number of flow sets is three but it is usually
38 # advisable to increase the number so that about one second can be buffered.
39 stream.register_managed_flow_set_pool(NUM_FLOW_SETS)
40
41 stream.start()
42 start = timer()
43 for i in range(NUM_ELEMENTS_TO_ACQUIRE):
44 composite, status, _ = stream.wait_for(TIMEOUT_MS)
45 with composite:
46 part = composite[0]
47 # try to get the composite's first element as an image
48 if i and i % FEEDBACK_INTERVAL == 0:
49 if isinstance(part, cvb.Image):
50 img: cvb.Image = part
51 print(f"acquired images: {i} | size: {img.width} x {img.height}")
52 else:
53 print(f"acquired composites: {i} which is not an image")
54
55 end = timer()
56 duration = end - start
57 # For RDMA streaming the data rate is usually interesting...
58 data_rate = payload_size * NUM_ELEMENTS_TO_ACQUIRE / (1000000 * duration)
59 stream.try_abort()
60
61 print(f"\nacquired {NUM_ELEMENTS_TO_ACQUIRE} buffers in {(duration * 1000):.2f} ms ( {data_rate:.2f} MB/s )")
62
63
64
The composite stream class.
Definition: __init__.py:841
Union[cvb.GenICamDevice, cvb.VinDevice, cvb.EmuDevice, cvb.VideoDevice, cvb.NonStreamingDevice] open(str provider, int acquisition_stack=cvb.AcquisitionStack.PreferVin)
Opens a device with the given provider and acquisition stack.
Definition: __init__.py:1629
List[cvb.DiscoveryInformation] discover_from_root(int flags=cvb.DiscoverFlags.FindAll, int time_span=300)
Discovers available devices / nodes depending on the given flags.
Definition: __init__.py:1609
The Common Vision Blox image.
Definition: __init__.py:2097