mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-13 04:30:28 +00:00
perf(zmq): optimize RX path using SIMD conversion and direct storage
Optimize the RX path by converting float complex samples received on ZMQ to int16 complex format using SIMD right inside the polling thread. This allows storing int16 complex (c16_t) samples directly inside the overflow_buffer, skipping a temporary float buffer allocation and a memcpy in the receive function. Signed-off-by: Bartosz Podrygajlo <bartosz.podrygajlo@openairinterface.org>
This commit is contained in:
@@ -63,18 +63,13 @@ bool zmq_tx_channel::align(uint64_t timestamp, std::chrono::milliseconds timeout
|
||||
void zmq_rx_channel::receive(c16_t *samples, size_t nsamps)
|
||||
{
|
||||
size_t samples_popped = 0;
|
||||
cf_t samples_float[nsamps];
|
||||
while (samples_popped < (size_t)nsamps && !stopped_) {
|
||||
size_t popped_now = buffer_.pop_samples(samples_float + samples_popped, nsamps - samples_popped);
|
||||
size_t popped_now = buffer_.pop_samples(samples + samples_popped, nsamps - samples_popped);
|
||||
samples_popped += popped_now;
|
||||
if (popped_now == 0) {
|
||||
usleep(100); // wait for more samples to arrive
|
||||
}
|
||||
}
|
||||
for (size_t i = 0; i < nsamps; i++) {
|
||||
samples[i].r = samples_float[i].r * c16_t_to_cf_t_factor + 0.5;
|
||||
samples[i].i = samples_float[i].i * c16_t_to_cf_t_factor + 0.5;
|
||||
}
|
||||
}
|
||||
void zmq_rx_channel::stop()
|
||||
{
|
||||
|
||||
@@ -36,11 +36,11 @@ class zmq_tx_channel {
|
||||
|
||||
class zmq_rx_channel {
|
||||
public:
|
||||
void *socket_;
|
||||
overflow_buffer<cf_t> buffer_;
|
||||
bool request_sent_;
|
||||
std::atomic<bool> stopped_;
|
||||
zmq_rx_channel(void *s, uint64_t buffer_size) : socket_(s), buffer_(buffer_size), stopped_(false)
|
||||
void *socket_;
|
||||
overflow_buffer<c16_t> buffer_;
|
||||
bool request_sent_;
|
||||
std::atomic<bool> stopped_;
|
||||
zmq_rx_channel(void *s, uint64_t buffer_size) : socket_(s), buffer_(buffer_size), stopped_(false)
|
||||
{
|
||||
}
|
||||
void receive(c16_t *samples, size_t nsamps);
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include <ring_buffer.h>
|
||||
#include <zmq.h>
|
||||
#include "zmq_imported.h"
|
||||
#include "zmq_simd.h"
|
||||
|
||||
#define ZMQ_SECTION "zmq"
|
||||
#define ZMQ_TX_CHANNELS "tx_channels"
|
||||
@@ -68,6 +69,7 @@ static void poll_thread(zmq_state_t *s)
|
||||
{
|
||||
s->poll_thread_running = true;
|
||||
unsigned char *rx_buffer = static_cast<unsigned char *>(malloc(rx_buffer_size));
|
||||
c16_t *rx_buffer_c16 = static_cast<c16_t *>(malloc(rx_buffer_size / sizeof(cf_t) * sizeof(c16_t)));
|
||||
const auto num_tx_channels = s->tx_stream.channels_.size();
|
||||
const auto num_rx_channels = s->rx_stream.channels_.size();
|
||||
std::vector<zmq_pollitem_t> items(num_tx_channels + num_rx_channels);
|
||||
@@ -145,7 +147,11 @@ static void poll_thread(zmq_state_t *s)
|
||||
}
|
||||
size_t num_samples_received = std::min(received_bytes, rx_buffer_size) / sizeof(cf_t);
|
||||
cf_t *samples = reinterpret_cast<cf_t *>(rx_buffer);
|
||||
size_t overflow = chan->buffer_.push_samples(samples, num_samples_received);
|
||||
convert_samples_avx512_rx(reinterpret_cast<const float *>(samples),
|
||||
reinterpret_cast<int16_t *>(rx_buffer_c16),
|
||||
num_samples_received * 2,
|
||||
c16_t_to_cf_t_factor);
|
||||
size_t overflow = chan->buffer_.push_samples(rx_buffer_c16, num_samples_received);
|
||||
if (rx_buffer_size < received_bytes) {
|
||||
overflow += chan->buffer_.push_zeros((received_bytes - rx_buffer_size) / sizeof(cf_t));
|
||||
}
|
||||
@@ -162,6 +168,7 @@ static void poll_thread(zmq_state_t *s)
|
||||
}
|
||||
}
|
||||
free(rx_buffer);
|
||||
free(rx_buffer_c16);
|
||||
}
|
||||
|
||||
static int zmq_write(openair0_device_t *device, openair0_timestamp_t timestamp, void **buff, int nsamps, int cc, int flags)
|
||||
|
||||
Reference in New Issue
Block a user