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.
This commit is contained in:
@@ -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();
|
||||
}
|
||||
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++) { // 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
|
||||
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;
|
||||
|
||||
Reference in New Issue
Block a user