Я работаю на x310 через двойную 10-гигабитную сеть Ethernet, оснащенную двумя базовыми дочерними платами tx rx. Я работаю на UHD версии 3.11.0. В идеале я хотел бы, чтобы два потока передачи и приема одновременно использовали оба канала для передачи и приема. Я не хочу использовать 2 x310s для 2 потоков приема и передачи
Когда я передаю и получаю в одно и то же время по одному и тому же каналу, я получаю много распечаток U на потери сигнала в консоли, независимо от скорости передачи. ОДНАКО, если я передаю и получаю по отдельным каналам (tx_streamer имеет stream_args на канале 1, а rx_streamer имеет stream_args на канале 0), это работает просто отлично.
Я приложил исходный код полной, но простой программы, которая, я надеюсь, продемонстрирует мою проблему. В этой программе создаются два потока: поток передачи и поток приема. Получающий поток постоянно получает данные в буфер и перезаписывает этот буфер новыми данными. Поток передачи постоянно передает 0 из предварительно заполненного буфера.
Если у кого-то есть x310, работающий через 10 Гбит / с Ethernet, можете ли вы скомпилировать и запустить мою программу, чтобы проверить, возникает ли эта проблема не только у меня?
Вот что мы уже тестировали:
Я работаю на серверной системе с двумя 12-ядерными процессорами Intel Xeon. (https://ark.intel.com/products/91767/Intel-Xeon-Processor-E5-2650-v4-30M-Cache-2_20-GHz). Моя сетевая карта рекомендованная x520 da2. Кто-то ранее предлагал NUMA быть проблемой, но я не думаю, что это так, поскольку программа работает, когда мы переключаемся на передачу и прием по отдельным каналам.
Поскольку программа прекрасно работает, когда мы передаем и принимаем по отдельным каналам, я уверен, что это не проблема питания процессора.
Я тестировал только передачу и только прием. Мы можем передавать со скоростью 200 мс / с по обоим каналам, и мы можем принимать со скоростью 200 мс / с по обоим каналам, но мы не можем передавать и принимать с одного и того же канала. Это говорит о том, что наша сетевая карта работает нормально, и мы можем справиться с высокой скоростью.
Я пробовал свою программу на UHD 3.10.2, и проблема все еще возникает
Я попытался установить tx_metadata за 2 секунды до передачи. Проблема все еще возникает.
Я попытался запустить пример программы txrx_loopback_from_file, и она работает для одновременного приема и передачи, но я понятия не имею, почему.
С последней точки зрения я считаю, что я как-то неправильно называю API UHD, но я понятия не имею, где ошибка. Любая помощь будет принята с благодарностью.
Спасибо,
Джейсон
#include <iostream>
#include <iomanip>
#include <stdlib.h>
#include <vector>
#include <csignal>
#include <thread>
#include <uhd/utils/thread_priority.hpp>
#include <uhd/utils/safe_main.hpp>
#include <uhd/usrp/multi_usrp.hpp>
#include <uhd/types/tune_request.hpp>
typedef std::complex<short> Complex;
// Constants and signal variables
static bool stop_signal_called = false;
const int NUM_CHANNELS = 1;
const int BUFF_SIZE = 64000;
//function prototypes here
void recvTask(Complex *buff, uhd::rx_streamer::sptr rx_stream);
void txTask(Complex *buff, uhd::tx_streamer::sptr tx_stream, uhd::tx_metadata_t md);
void sig_int_handler(int){
std::cout << "Interrupt Signal Received" << std::endl;
stop_signal_called = true;
}
int UHD_SAFE_MAIN(int argc, char *argv[]) {
uhd::set_thread_priority_safe();
//type=x300,addr=192.168.30.2,second_addr=192.168.40.2
std::cout << std::endl;
std::cout << boost::format("Creating the usrp device") << std::endl;
uhd::usrp::multi_usrp::sptr usrp = uhd::usrp::multi_usrp::make(std::string("type=x300,addr=192.168.30.2"));
std::cout << std::endl;
//set stream args
uhd::stream_args_t stream_args("sc16");
double samp_rate_tx = 10e6;
double samp_rate_rx = 10e6;
uhd::tune_request_t tune_request(0);
//Lock mboard clocks
usrp->set_clock_source(std::string("internal"));
//set rx parameters
usrp->set_rx_rate(samp_rate_rx);
usrp->set_rx_freq(tune_request);
usrp->set_rx_gain(0);
//set tx parameters
usrp->set_tx_rate(samp_rate_tx);
usrp->set_tx_freq(tune_request);
usrp->set_tx_gain(0);
std::signal(SIGINT, &sig_int_handler);
std::cout << "Press Ctrl + C to stop streaming..." << std::endl;
//create buffers, 2 per channel (1 for tx, 1 for rx)
// transmitting complex shorts -> typedef as Complex
Complex *rx_buffs[NUM_CHANNELS];
Complex *tx_buffs[NUM_CHANNELS];
for (int i = 0; i < NUM_CHANNELS; i++){
rx_buffs[i] = new Complex[BUFF_SIZE];
tx_buffs[i] = new Complex[BUFF_SIZE];
// only transmitting 0's
std::fill(tx_buffs[i], tx_buffs[i]+BUFF_SIZE, 0);
}
//////////////////////////////////////////////////////////////////////////////
////////////////START RECEIVE AND TRANSMIT THREADS////////////////////////////
//////////////////////////////////////////////////////////////////////////////
printf("setting up threading\n");
//reset usrp time
usrp -> set_time_now(uhd::time_spec_t(0.0));
// set up RX streams and threads
std::thread rx_threads[NUM_CHANNELS];
uhd::rx_streamer::sptr rx_streams[NUM_CHANNELS];
for (int i = 0; i < NUM_CHANNELS; i++){
stream_args.channels = std::vector<size_t>(1,i);
rx_streams[i] = usrp->get_rx_stream(stream_args);
//setup streaming
auto stream_mode = uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS;
uhd::stream_cmd_t stream_cmd(stream_mode);
stream_cmd.num_samps = 0;
stream_cmd.stream_now = true;
stream_cmd.time_spec = uhd::time_spec_t();
rx_streams[i]->issue_stream_cmd(stream_cmd);
//start rx thread
std::cout << "Starting rx thread " << i << std::endl;
rx_threads[i] = std::thread(recvTask,rx_buffs[i],rx_streams[i]);
}// set up TX streams and threads
std::thread tx_threads[NUM_CHANNELS];
uhd::tx_streamer::sptr tx_streams[NUM_CHANNELS];
// set up TX metadata
uhd::tx_metadata_t md;
md.start_of_burst = true;
md.end_of_burst = false;
md.has_time_spec = true;
// start transmitting 2 seconds later
md.time_spec = uhd::time_spec_t(2);
for (int i = 0; i < NUM_CHANNELS; i++){
//does not work when we transmit and receive on same channel,
//if we change to stream_args.channels = std::vector<size_t> (1,1), this works for 1 channel.
stream_args.channels = std::vector<size_t>(1,i);
tx_streams[i] = usrp->get_tx_stream(stream_args);
//start the thread
std::cout << "Starting tx thread " << i << std::endl;
tx_threads[i] = std::thread(txTask,tx_buffs[i],tx_streams[i],md);
}
printf("Waiting to join threads\n");
for (int i = 0; i < NUM_CHANNELS; i++){
//join threads
tx_threads[i].join();
rx_threads[i].join();
}
return EXIT_SUCCESS;
}
//////////////////////////////////////////////////////////////////////////////
////////////////RECEIVE AND TRANSMIT THREAD FUNCTIONS/////////////////////////
//////////////////////////////////////////////////////////////////////////////
void recvTask(Complex *buff, uhd::rx_streamer::sptr rx_stream){
uhd::rx_metadata_t md;
unsigned overflows = 0;
//receive loop
while(!stop_signal_called){
size_t amount_received = rx_stream->recv(buff,BUFF_SIZE,md,3.0);
if (amount_received != BUFF_SIZE){ printf("receive not equal\n");}
//handle the error codes
switch(md.error_code){
case uhd::rx_metadata_t::ERROR_CODE_NONE:
break;
case uhd::rx_metadata_t::ERROR_CODE_TIMEOUT:
std::cerr << "T";
continue;
case uhd::rx_metadata_t::ERROR_CODE_OVERFLOW:
overflows++;
std::cerr << "Got an Overflow Indication" << std::endl;
continue;
default:
std::cout << boost::format(
"Got error code 0x%x, exiting loop...") % md.error_code << std::endl;
goto done_loop;
}
} done_loop:
// tell receive to stop streaming
auto stream_cmd = uhd::stream_cmd_t(uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS);
rx_stream->issue_stream_cmd(stream_cmd);
//finished
std::cout << "Overflows=" << overflows << std::endl << std::endl;
}
void txTask(Complex *buff, uhd::tx_streamer::sptr tx_stream, uhd::tx_metadata_t md){
//transmit loop
while(!stop_signal_called){
size_t samples_sent = tx_stream->send(buff,BUFF_SIZE,md);
md.start_of_burst = false;
md.has_time_spec = false;
}
//send a mini EOB packet
md.end_of_burst = true;
tx_stream -> send("",0,md);
printf("End transmit \n");
}
Задача ещё не решена.
Других решений пока нет …