C++ 从同一信道发送和接收时,x310上的缓冲区运行不足

C++ 从同一信道发送和接收时,x310上的缓冲区运行不足,c++,usrp,uhd,C++,Usrp,Uhd,我在x310上运行,通过双万兆以太网,配备了两个基本的tx-rx子板。我正在运行UHD版本3.11.0。理想情况下,我想要两个同时发送和接收的流,利用两个通道来发送和接收。我不想对2个接收和发送流使用2个x310s 当我在同一信道上同时发送和接收信号时,无论速率如何,我都会将大量的U输出到控制台信令下溢但是,如果我在单独的通道上发送和接收(tx_拖缆在通道1上有stream_参数,rx_拖缆在通道0上有stream_参数),它工作正常。 我附上了一个完整但简单的程序的源代码,希望能证明我的问题。

我在x310上运行,通过双万兆以太网,配备了两个基本的tx-rx子板。我正在运行UHD版本3.11.0。理想情况下,我想要两个同时发送和接收的流,利用两个通道来发送和接收。我不想对2个接收和发送流使用2个x310s

当我在同一信道上同时发送和接收信号时,无论速率如何,我都会将大量的U输出到控制台信令下溢但是,如果我在单独的通道上发送和接收(tx_拖缆在通道1上有stream_参数,rx_拖缆在通道0上有stream_参数),它工作正常。

我附上了一个完整但简单的程序的源代码,希望能证明我的问题。在这个程序中,创建了两个线程:一个传输线程和一个接收线程。接收线程不断地将数据接收到缓冲区,并用新数据覆盖该缓冲区。传输线程不断地从预填充的缓冲区传输0

如果有人的x310在10Gbps以太网上运行,您能编译并运行我的程序来测试这个问题是否不仅仅发生在我身上吗

以下是我们已经测试过的内容:

  • 我运行的服务器系统运行两个12核intel xeon处理器。(). 我的网卡是推荐的x520 da2。以前有人建议NUMA是一个问题,但我认为情况并非如此,因为当我们切换到在不同的频道上发送和接收时,程序可以工作

  • 由于当我们在不同的通道上进行传输和接收时,程序工作正常,我相信这不是CPU电源问题

  • 我只测试了发送和接收。我们可以在两个通道上以200MS/s的速度传输,也可以在两个通道上以200MS/s的速度接收,但我们不能从同一个通道上发送和接收。这表明我们的网卡工作正常,我们可以处理高速率

  • 我在UHD 3.10.2上尝试了我的程序,但问题仍然存在

  • 我已尝试设置发送前等待2秒的tx_元数据。问题仍然存在

  • 我试着从_文件运行示例程序txrx_loopback_,它可以同时接收和发送,但我不知道为什么

从最后一点来看,我相信我在某种程度上调用uhd API是错误的,但我不知道错误在哪里。任何帮助都将不胜感激

谢谢

杰森

#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
typedef-std::复杂复合体;
//常数和信号变量
静态布尔停止信号调用=假;
const int NUM_CHANNELS=1;
常量int BUFF_SIZE=64000;
//这里的函数原型
无效接收任务(复杂*buff,uhd::rx_拖缆::sptr rx_流);
void txTask(复杂*buff,uhd::tx_拖缆::sptr tx_流,uhd::tx_元数据\u md);
无效信号处理程序(int){
std::无法设置发送频率(调谐请求);
usrp->设置发送增益(0);
标准::信号(SIGINT和sig_int_处理器);
标准::cout
#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");  
}