Commit 033aed73 authored by Bartosz Podrygajlo's avatar Bartosz Podrygajlo

Rfsim: Optimization for simple configurations

 - Added first beam optimization to combine_tx_buffers.
 - Added first beam & first peer optimization to rfsimulator_read_internal

This results in significant speed up for the first rx beam, first tx
beam and first peer which is the base case with beam simulation disabled.
parent c587aab6
......@@ -235,7 +235,7 @@ void update_channel_model(channel_desc_t *channelDesc, uint64_t TS)
either we regenerate the channel (call again random_channel(desc,0)), or we keep it over subframes
legacy: we regenerate each sub frame in UL, and each frame only in DL
*/
void rxAddInput(const c16_t **input_sig,
void rxAddInput(c16_t **input_sig,
cf_t *after_channel_sig,
int rxAnt,
channel_desc_t *channelDesc,
......
......@@ -24,7 +24,7 @@
#ifndef __RFSIMULATOR_H
#define __RFSIMULATOR_H
#include <stdbool.h>
void rxAddInput(const c16_t **input_sig,
void rxAddInput(c16_t **input_sig,
cf_t *after_channel_sig,
int rxAnt,
channel_desc_t *channelDesc,
......
......@@ -1045,17 +1045,18 @@ static std::vector<int> get_beam_ids(uint64_t beam_map)
* @param num_aatx The number of antennas to process.
* @param num_samples The number of samples to process.
* @param rx_beam_id Receiver configured beam id for the timestamp
* @param samples Pointer to the output buffer where combined samples will be stored.
* @return A vector of vectors containing the combined samples for each antenna.
*/
static std::vector<std::vector<c16_t>> combine_received_beams(rfsimulator_state_t *t,
std::queue<rfsim_packet_t *> &received_packets,
uint64_t start_timestamp,
int num_aatx,
size_t num_samples,
int rx_beam_id)
static void combine_received_beams(rfsimulator_state_t *t,
std::queue<rfsim_packet_t *> &received_packets,
uint64_t start_timestamp,
int num_aatx,
size_t num_samples,
int rx_beam_id,
c16_t **samples)
{
// Assume received_packets is ordered by timestamp
std::vector<std::vector<c16_t>> ant_buffers(num_aatx, std::vector<c16_t>(num_samples, {0, 0}));
std::queue<rfsim_packet_t *> packets_copy = received_packets;
while (!packets_copy.empty()) {
rfsim_packet_t *pkt = packets_copy.front();
......@@ -1081,16 +1082,38 @@ static std::vector<std::vector<c16_t>> combine_received_beams(rfsimulator_state_
for (int aatx = 0; aatx < num_aatx; aatx++) {
c16_t *buffer = (c16_t *)pkt->payload;
c16_t *tx_ant_buffer_in = &buffer[(num_aatx * beam + aatx) * pkt->header.size + read_start_idx];
for (int s = write_start_idx; s < write_end_idx; s++) {
ant_buffers[aatx][s].r += tx_ant_buffer_in->r * gain_linear;
ant_buffers[aatx][s].i += tx_ant_buffer_in->i * gain_linear;
tx_ant_buffer_in++;
if (beam == 0) {
// For the first beam, we can directly copy the samples
if (gain_dB == 0.0f) {
// If gain is 0 dB, we can use memcpy for efficiency
memcpy(&samples[aatx][write_start_idx], tx_ant_buffer_in, (write_end_idx - write_start_idx) * sizeof(c16_t));
} else {
for (int s = write_start_idx; s < write_end_idx; s++) {
samples[aatx][s].r = tx_ant_buffer_in->r * gain_linear;
samples[aatx][s].i = tx_ant_buffer_in->i * gain_linear;
tx_ant_buffer_in++;
}
}
} else {
// For subsequent beams, we need to ensure we accumulate the samples
if (gain_dB == 0.0f) {
for (int s = write_start_idx; s < write_end_idx; s++) {
samples[aatx][s].r += tx_ant_buffer_in->r;
samples[aatx][s].i += tx_ant_buffer_in->i;
tx_ant_buffer_in++;
}
} else {
for (int s = write_start_idx; s < write_end_idx; s++) {
samples[aatx][s].r += tx_ant_buffer_in->r * gain_linear;
samples[aatx][s].i += tx_ant_buffer_in->i * gain_linear;
tx_ant_buffer_in++;
}
}
}
}
}
packets_copy.pop();
}
return ant_buffers;
}
static bool flushInput(rfsimulator_state_t *t, int timeout, bool first_time)
......@@ -1164,11 +1187,13 @@ static void rfsimulator_read_internal(rfsimulator_state_t *t,
openair0_timestamp timestamp,
int nsamps,
int nbAnt,
int rx_beam_id)
int rx_beam_id,
bool is_first_beam)
{
cf_t temp_array[nbAnt][nsamps];
bool channel_modelling = false;
// Add all input nodes signal in the output buffer
bool is_first_peer = true;
for (int sock = 0; sock < MAX_FD_RFSIMU; sock++) {
buffer_t *ptr = &t->buf[sock];
......@@ -1188,38 +1213,52 @@ static void rfsimulator_read_internal(rfsimulator_state_t *t,
}
const uint64_t channel_offset = ptr->channel_model->channel_offset;
const uint64_t channel_length = ptr->channel_model->channel_length;
std::vector<std::vector<c16_t>> ant_buffers = combine_received_beams(t,
ptr->received_packets,
timestamp - channel_offset - (channel_length - 1),
ptr->nbAnt,
nsamps + channel_length - 1,
rx_beam_id);
const c16_t *input[ant_buffers.size()];
std::vector<std::vector<c16_t>> ant_buffers(ptr->nbAnt, std::vector<c16_t>(nsamps + channel_length - 1, {0, 0}));
c16_t *input[ant_buffers.size()];
for (uint aatx = 0; aatx < ant_buffers.size(); aatx++) {
input[aatx] = ant_buffers[aatx].data();
}
combine_received_beams(t,
ptr->received_packets,
timestamp - channel_offset - (channel_length - 1),
ptr->nbAnt,
nsamps + channel_length - 1,
rx_beam_id,
input);
for (int aarx = 0; aarx < nbAnt; aarx++) {
rxAddInput(input, temp_array[aarx], aarx, ptr->channel_model, nsamps, timestamp);
}
} else {
std::vector<std::vector<c16_t>> ant_buffers =
combine_received_beams(t, ptr->received_packets, timestamp, ptr->nbAnt, nsamps, rx_beam_id);
for (int aarx = 0; aarx < nbAnt; aarx++) {
double H_awgn_mimo_coeff[ant_buffers.size()];
for (int aatx = 0; aatx < (int)ant_buffers.size(); aatx++) {
uint32_t ant_diff = std::abs(aatx - aarx);
H_awgn_mimo_coeff[aatx] = ant_diff ? (0.2 / ant_diff) : 1.0;
if (is_first_beam && is_first_peer && (ptr->nbAnt == 1 || nbAnt == 1)) {
// optimization: The buffer is uninitialized so samples can be written directly in the buffer
combine_received_beams(t, ptr->received_packets, timestamp, 1, nsamps, rx_beam_id, samples);
} else {
std::vector<std::vector<c16_t>> ant_buffers(ptr->nbAnt, std::vector<c16_t>(nsamps, {0, 0}));
c16_t *input[ant_buffers.size()];
for (uint aatx = 0; aatx < ant_buffers.size(); aatx++) {
input[aatx] = ant_buffers[aatx].data();
}
for (uint aatx = 0; aatx < ant_buffers.size(); aatx++) { // sum up signals from nbAnt_tx antennas
for (int i = 0; i < nsamps; i++) { // loop over nsamps
samples[aarx][i].r += ant_buffers[aatx][i].r * H_awgn_mimo_coeff[aatx];
samples[aarx][i].i += ant_buffers[aatx][i].i * H_awgn_mimo_coeff[aatx];
} // end for a_tx
} // end for i (number of samps)
} // end for a_rx
combine_received_beams(t, ptr->received_packets, timestamp, ptr->nbAnt, nsamps, rx_beam_id, input);
for (int aarx = 0; aarx < nbAnt; aarx++) {
double H_awgn_mimo_coeff[ant_buffers.size()];
for (int aatx = 0; aatx < (int)ant_buffers.size(); aatx++) {
uint32_t ant_diff = std::abs(aatx - aarx);
H_awgn_mimo_coeff[aatx] = ant_diff ? (0.2 / ant_diff) : 1.0;
}
for (uint aatx = 0; aatx < ant_buffers.size(); aatx++) {
for (int i = 0; i < nsamps; i++) {
samples[aarx][i].r += ant_buffers[aatx][i].r * H_awgn_mimo_coeff[aatx];
samples[aarx][i].i += ant_buffers[aatx][i].i * H_awgn_mimo_coeff[aatx];
}
}
}
}
}
}
is_first_peer = false;
}
bool apply_global_noise = get_noise_power_dBFS() != INVALID_DBFS_VALUE;
......@@ -1347,7 +1386,7 @@ static int rfsimulator_read_beams(openair0_device *device,
for (int i = 0; i < nbAnt; i++) {
samples_beam[i] = (c16_t *)samplesVoid[beam][i] + timestamp - t->nextRxTstamp;
}
rfsimulator_read_internal(t, samples_beam, timestamp, nsamps_beam_map, nbAnt, rx_beam_ids[beam]);
rfsimulator_read_internal(t, samples_beam, timestamp, nsamps_beam_map, nbAnt, rx_beam_ids[beam], beam == 0);
}
timestamp += nsamps_beam_map;
nsamps_to_process -= nsamps_beam_map;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment