Main Content

Verify Performance of 6G AI-Native Receiver Using MATLAB and PyTorch Coexecution

Since R2025a

This example shows how to verify and test a PyTorch™ AI-native receiver and compare it with a conventional 5G receiver using both multi-process central processing unit (CPU) and graphics processing unit (GPU) hardware acceleration.

In this example, you generate a stream of data in MATLAB and perform inference using the PyTorch network in an online inference workflow. With this process, you can use deep learning models for training and inference without saving the training data.

The basic steps to validate the PyTorch network are as follows:

  1. Set up the Python environment and verify that the required packages are installed.

  2. Specify the test parameters.

  3. Load the PyTorch network.

  4. Validate the network using online data generation and testing.

  5. Visualize and compare results with a conventional 5G receiver, which serves as a benchmark.

System Description

This example provides a testbench for AI-native convolutional receivers, featuring online data generation, inference, and hardware acceleration capabilities. The AI-native fully convolutional receiver system replaces 5G receiver operations with convolutional neural networks (CNNs) to enhance system performance under severe channel impairments and sparse pilot configurations. Traditional 5G receivers struggle to perform under such conditions. For more information about the AI-native receivers and implementation details, see the AI-Native Fully Convolutional Receiver example.

This figure shows the physical uplink shared channel (PUSCH) simulation that measures coded bit-error-ratio (BER) and throughput metrics using both the AI-native convolutional receiver and the conventional 5G receiver as a benchmark. The deeprx.py script loads the model and performs log-likelihood-ratio (LLR) predictions to replace the channel estimation, channel equalization, and symbol demodulation functionalities of the conventional 5G receiver. The deeprx_model.py script manages the model creation and parameter loading. The deeprx_30k.pth file contains the model state dictionary, including model parameters (weights and biases) and optimizer states.

Simulation workflow comparing a conventional 5G receiver with the AI-native receiver

Step 1: Set Up Python Environment

Configure the Python environment necessary for running your trained PyTorch network. Before running this example, set up the Python environment as explained in the PyTorch Coexecution topic. Specify the full or relative path of the Python executable below. This path can also point to a virtual environment. If you are running the example on Windows®, specify the path to the pythonw.exe file. The example runs using the OutOfProcess execution mode of the Python interpreter. If you use the InProcess execution mode instead, MATLAB and PyTorch might have library conflicts. To learn more about InProcess vs. OutOfProcess, see pyenv.

% Configure the Python environment
simParameters.PythonExecutionMode = "OutOfProcess";

% Paths for the Python executable:
% ..\venv\Scripts\pythonw.exe for Windows and ../venv/bin/python3 for Linux
simParameters.PythonPath          = "relative_path_to_python_executable";

% Path to the REQUIREMENTS.txt file
simParameters.PythonRequirements  = "requirements_6GVerify.txt";

The helperSetupPyenv function sets the Python environment in MATLAB according to the options you select and verifies that the libraries listed in the requirements_6GVerify.txt file are installed.

currentPyEnv = helperSetupPyenv(simParameters.PythonPath, ...
                                simParameters.PythonExecutionMode, ...
                                simParameters.PythonRequirements);
Setting up Python environment
Parsing requirements_6GVerify.txt 
Checking required package 'torch'
Checking required package 'numpy'
Required Python libraries are installed.

Step 2: Specify Test Parameters

To test the performance of your AI-native receiver network, define the carrier, uplink shared channel (UL-SCH), PUSCH, and PUSCH demodulation reference signal (DM-RS) configurations along with the channel parameters. You can also select the propagation channels in which you want to validate your model. The example supports both clustered delay line (CDL) and tapped delay line (TDL) propagation channels.

The example calculates and compares your trained network's performance with conventional 5G receiver. The signal-to-noise ratio (SNR) parameter represents the SNR per resource element (RE) and per antenna element. For further explanation of the SNR definition, see the SNR Definition Used in Link Simulations example. You can reduce the total execution time by executing each SNR point on each worker. To enable CPU-based hardware acceleration for the end-to-end uplink (UL) PUSCH simulation in test data generation, set simParameters.UseParallel to true. This process requires Parallel Computing Toolbox™.

% End-to-end simulation parameters for testing the AI-native and
% conventional 5G receivers
simParameters.UseParallel             = false; % If true, enable parallel processing; otherwise, execute serially
simParameters.ChannelModel            = "TDL-E"; % Channel models for testing: "CDL-A", "CDL-E", "TDL-A", "TDL-E"
simParameters.DelaySpread             = 100e-9; % Delay spread in seconds, range: [10e-9, 300e-9]
simParameters.MaximumDopplerShift     = 250; % Maximum Doppler shift in Hz, range: [0, 500]
simParameters.SNRInVec                = 0:10; % SNR range in dB for evaluation
simParameters.ModulationType          = "QPSK"; % Modulation type: "QPSK" or "16QAM"
simParameters.DMRSAdditionalPosition  = 0; % DMRS additional position: 0 or 1
simParameters.DMRSConfigurationType   = 2; % DMRS configuration type: 1 or 2
simParameters.NFrames                 = 5; % Number of frames for the simulation
simParameters.PerfectChannelEstimator = false; % Use perfect channel estimation if true

% Additional UL PUSCH simulation parameters comes from [1]
simParameters.CarrierFrequency  = 3.5e9;    % Carrier frequency in Hz
simParameters.NSizeGrid         = 26;       % Number of resource blocks (26 RBs at 15 kHz SCS)
simParameters.SubcarrierSpacing = 15;       % Subcarrier spacing in kHz
simParameters.CodeRate          = 658/1024; % Code rate used to calculate transport block size
simParameters                   = hGetAdditionalSystemParameters(simParameters, DisplayParameterSummary=false);

Step 3: Load Your PyTorch Network

In this section, you load and inspect your trained AI-native receiver model in the MATLAB workspace. Follow these steps to load the PyTorch network into the example workspace and inspect its properties:

  1. Locate the model file using the simParameters.ModelPath parameter.

  2. Create a PyTorch model instance using the hCreateTorchDeepRx function and load the trained network parameters.

  3. Display the model details.

Locate the model parameters file in .pth format in the example workspace for validation. By default, this example keeps the model's parameter dictionary file in a .zip file, which the hCreateTorchDeepRx function unzips.

simParameters.ModelPath   = "deeprx_30k.pth";
simParameters.ModelInput  = simParameters.InputSize;
simParameters.ModelOutput = [simParameters.ModelInput(1:2) 4];

Create a PyTorch DeepRx network instance in MATLAB using the hCreateTorchDeepRx function, specifying the input and output sizes of [F,S,4Nrx] and [F,S,B], respectively. The parameters F, S, and Nrx represent the total number of subcarriers, the total number of OFDM symbols in the input resource grid, and the number of receive antennas. The input resource grid consists of a combination of the received data grid (rxGrid), pilot symbols grid (dmrsGrid), and raw estimation of the channels (rawChanEstGrid). Similarly, the parameter B is the number of bits per transmitted symbol. The model inputs and outputs are fixed at [312,14,10] and [312,14,4], respectively, because the example uses the same training parameters presented in the AI-Native Fully Convolutional Receiver example. For further details of the AI-native model architecture, see the Details of AI-Native Fully Convolutional Receiver Network. Once you load the network, you can test it for 16-QAM or QPSK modulations, since the bit masking supports constellation sizes less than or equal to that of the training modulation type [1].

  • If Evaluate is true, the hCreateTorchDeepRx function instantiates the model in evaluation mode using deeprx_30k.pth and loads the trained model and optimizer parameters. This change affects the behavior of the batch normalization layers in the DeepRx architecture.

  • If Evaluate is false, the model instantiates in training mode, and the model and optimizer parameters are loaded.

  • You can also instantiate the untrained model without loading the trained model parameters by setting simParameters.ModelPath to string.empty or [].

model = hCreateTorchDeepRx(simParameters, Evaluate=true);

Display the network summary to show the model building blocks and the number of trainable parameters.

modelParameters = py.deeprx.info(model);
displayModelSummary(modelParameters);
----------------------------------------
          Neural Network Summary
----------------------------------------

  - Total number of learnables  : 1.2325 million
  - Number of layers            : 13

  - Model building blocks       :
       1) conv_in
       2) resnet_block_1
       3) resnet_block_2
       4) resnet_block_3
       5) resnet_block_4
       6) resnet_block_5
       7) resnet_block_6
       8) resnet_block_7
       9) resnet_block_8
      10) resnet_block_9
      11) resnet_block_10
      12) resnet_block_11
      13) conv_out

Step 4: Test and Compare the AI-Native Receiver Against the Benchmark

In this section, you generate a batch of test data, make predictions using the PyTorch network and conventional 5G receiver, and calculate and compare the coded BER and throughput values. The evaluateLinkPerformance function evaluates the performance of the AI-native and conventional 5G receivers based on the simulation parameters in Step 2.

  • If simParameters.UseParallel is true, the example creates parfeval future objects and schedules the hGetFeaturesAndLabels function to execute on each worker using the parfeval call. Each worker processes an SNR point (simParameters.SNRIn) asynchronously, which may cause the retrieved coded BER and throughput results to be out of order. To address this, the example organizes the results before plotting.

Diagram illustrating CPU and GPU hardware acceleration when MATLAB and PyTorch scripts are called asynchronously

  • Otherwise, the simulation generates a batch of test data for a given SNR point (simParameters.SNRIn) and calculates coded BER and throughput metrics for both the AI-native receiver and conventional 5G receivers consecutively in a single CPU process.

The example uses native CUDA-based GPU acceleration in PyTorch (if available) by sending the model to a GPU in Step 3. Similarly, the predict function in the deeprx module sends the test data tensors to a for GPU-accelerated predictions.

To simulate the end-to-end UL PUSCH link call the hCreateTorchDeepRx function inside the hGetFeaturesAndLabels function. The following code snippets show how the AI-native and 5G conventional receivers determine the LLR values inside the hGetFeaturesAndLabels function with the default example parameterization.

  • This code snippet represents the LLR prediction and ulschLLRs calculation when you pass the AI-native receiver model to the hGetFeaturesAndLabels function.

% Predict LLRs using the input resource grids
%
% (i) If the model is a PyTorch network, use the trained model (opts.Net) and test resource grids (X) to predict the LLRs (L).
% This option uses a GPU for predictions implicitly via the predict call inside the deeprx.py module if a GPU is available.
%
% (ii) If the model is a dlnetwork object, use the DeepRx network and dlarray resource grids to predict the LLRs.
% This option uses a GPU for predictions if a GPU is available.
if opts.UsePyTorchNeuralReceiver
    L = single(py.deeprx.predict(opts.Net, X));
else % dlnetwork
    if canUseGPU
        L = predict(opts.Net, gpuArray(dlarray(X, 'SSCB')));
    else
        L = predict(opts.Net, dlarray(X, 'SSCB'));
    end
end

% Extract the utilized LLR values.
% Note that the LLR negation results from the difference between the LLR definition in `ldpcDecode` and the BCE loss functions.
Qm = puschIndicesInfo.G / puschIndicesInfo.Gd / pusch.NumLayers;
extractedLLRs = nrExtractResources(double(puschIndices), -L(:, :, 1:Qm));
ulschLLRs = reshape(gather(extractdata(extractedLLRs.')), [], 1);
ulschLLRs = nrPUSCHDescramble(ulschLLRs, simLocal.PUSCH.NID, simLocal.PUSCH.RNTI, []);
  • Similarly, this code snippet shows the ulschLLRs calculation for practical channel estimation when you use the 5G conventional receiver in the hGetFeaturesAndLabels function.

% Practical channel estimation using the PUSCH DM-RS for each layer
dmrsLayerSymbols = nrPUSCHDMRS(carrier, puschNonCodebook);
dmrsLayerIndices = nrPUSCHDMRSIndices(carrier, puschNonCodebook);
[estChannelGrid, noiseEst] = nrChannelEstimate(carrier, rxGrid, dmrsLayerIndices, dmrsLayerSymbols, 'CDMLengths', pusch.DMRS.CDMLengths);

% Extract PUSCH resource elements from the received grid
[puschRx, puschHest] = nrExtractResources(puschIndices, rxGrid, estChannelGrid);

% Equalization using MMSE
[puschEq, csi] = nrEqualizeMMSE(puschRx, puschHest, noiseEst);

% Decode PUSCH physical channel
[ulschLLRs, rxSymbols] = nrPUSCHDecode(carrier, puschNonCodebook, puschEq, noiseEst);
% Link performance evaluation; results will return coded BER and throughput
[resultsRX, resultsAI] = evaluateLinkPerformance(simParameters, model);
- Test data generation: Serial execution
- Inference environment: CUDA

Simulating DeepRx and conventional receivers for 11 SNR points...

(  9.09%) SNRIn:  +0.00 dB  |  Channel: TDL-E  |  Delay Spread: 1.00e-07  |  Max Doppler shift: 250.00 | DMRS Add. Pos. / Config. Type: 0 / 2
( 18.18%) SNRIn:  +1.00 dB  |  Channel: TDL-E  |  Delay Spread: 1.00e-07  |  Max Doppler shift: 250.00 | DMRS Add. Pos. / Config. Type: 0 / 2
( 27.27%) SNRIn:  +2.00 dB  |  Channel: TDL-E  |  Delay Spread: 1.00e-07  |  Max Doppler shift: 250.00 | DMRS Add. Pos. / Config. Type: 0 / 2
( 36.36%) SNRIn:  +3.00 dB  |  Channel: TDL-E  |  Delay Spread: 1.00e-07  |  Max Doppler shift: 250.00 | DMRS Add. Pos. / Config. Type: 0 / 2
( 45.45%) SNRIn:  +4.00 dB  |  Channel: TDL-E  |  Delay Spread: 1.00e-07  |  Max Doppler shift: 250.00 | DMRS Add. Pos. / Config. Type: 0 / 2
( 54.55%) SNRIn:  +5.00 dB  |  Channel: TDL-E  |  Delay Spread: 1.00e-07  |  Max Doppler shift: 250.00 | DMRS Add. Pos. / Config. Type: 0 / 2
( 63.64%) SNRIn:  +6.00 dB  |  Channel: TDL-E  |  Delay Spread: 1.00e-07  |  Max Doppler shift: 250.00 | DMRS Add. Pos. / Config. Type: 0 / 2
( 72.73%) SNRIn:  +7.00 dB  |  Channel: TDL-E  |  Delay Spread: 1.00e-07  |  Max Doppler shift: 250.00 | DMRS Add. Pos. / Config. Type: 0 / 2
( 81.82%) SNRIn:  +8.00 dB  |  Channel: TDL-E  |  Delay Spread: 1.00e-07  |  Max Doppler shift: 250.00 | DMRS Add. Pos. / Config. Type: 0 / 2
( 90.91%) SNRIn:  +9.00 dB  |  Channel: TDL-E  |  Delay Spread: 1.00e-07  |  Max Doppler shift: 250.00 | DMRS Add. Pos. / Config. Type: 0 / 2
(100.00%) SNRIn: +10.00 dB  |  Channel: TDL-E  |  Delay Spread: 1.00e-07  |  Max Doppler shift: 250.00 | DMRS Add. Pos. / Config. Type: 0 / 2

Step 5: Visualize Results

Use the visualizePerformance local function to plot the coded BER and throughput values of the AI-native receiver and conventional 5G receivers against the SNR range. These figures show that the AI-native receiver significantly outperforms the conventional receiver for the given scenario parameters.

% Plot Coded BER vs. SNR and Throughput (%) vs. SNR
visualizePerformance(simParameters, resultsRX, resultsAI);

Figure contains 2 axes objects. Axes object 1 with xlabel SNR (dB), ylabel Coded BER contains 2 objects of type line. These objects represent DeepRx (PyTorch), Conventional 5G Rx. Axes object 2 with xlabel SNR (dB), ylabel Throughput (%) contains 2 objects of type line. These objects represent DeepRx (PyTorch), Conventional 5G Rx.

Details of AI-Native Fully Convolutional Receiver Network

The AI-native fully convolutional receiver, known as DeepRx, uses a CNN architecture that combines a Residual Network (ResNet) with full preactivation [2] and extreme Inception (Xception) architectures [3]. The network takes resource grids as input for an UL single-input-multiple-output (SIMO) system, where the grids have dimensions [FS4Nrx+2]. The access network node receives the grids and routes them through the entry stage. After this stage, the resource grids proceed to the middle stage, which utilizes 11 ResNet blocks with various dilation factors. The architecture employs identity shortcuts between feature maps where input and output sizes match. Conversely, it uses projection shortcuts where input and output sizes differ, allowing the addition operation in each ResNet block to occur. To reduce computational complexity, each ResNet block implements depthwise separable convolutions. Finally, the processed resource block from the middle stage advances to the exit stage, which includes batch normalization, ReLU, and a final convolution stage with an output size of [FSB].

The example uses a trained model, deeprx_30k.mat, which is compressed and included as a supporting file in the example folder under the name torch_trained_network.zip. For training details and solver parameterization, see the AI-Native Fully Convolutional Receiver example. This diagram illustrates the architectural flow of the AI-native fully convolutional receiver model.

Detailed depiction of the building blocks of the AI-native fully convolutional receiver

Local Functions

function displayModelSummary(modelParameters)
    % Convert model parameters to a cell array
    params = cell(modelParameters);

    % Extract and filter unique layer names
    layerNames = unique(string(params{2}), "stable");
    layerNames = layerNames(~ismember(layerNames, ["", "bn", "relu"]));

    % Print the network summary
    border = repmat('-', 1, 40);
    fprintf('\n%s\n', border);
    fprintf('          Neural Network Summary\n');
    fprintf('%s\n\n', border);
    fprintf('  %-30s: %.4f million\n', '- Total number of learnables', double(params{1})/1e6);
    fprintf('  %-30s: %d\n', '- Number of layers', length(layerNames));
    fprintf('\n  %-30s:\n', '- Model building blocks');
    
    % Display unique layerNames with aligned indices
    indexWidth = length(num2str(length(layerNames)));
    arrayfun(@(i) fprintf(['      %' num2str(indexWidth) 'd) %s\n'], i, layerNames{i}), 1:length(layerNames));
end

function visualizePerformance(simParameters, resultsRX, resultsAIML)
    % Visualize the performance of the system by plotting coded BER and
    % throughput results against SNR for both MMSE based conventional 5G
    % and PyTorch AI-Native receiver

    % Create a figure object for the plots
    co = colororder;
    f = figure;
    f.Position = [0 0 1000 450];
    t = tiledlayout(1, 2, "TileSpacing", "compact");
    
    % Plot coded BER against SNR
    nexttile;
    semilogy(simParameters.SNRInVec, [resultsAIML.CodedBER], "-*", "Color", co(5,:), "LineWidth", 1.5, "MarkerSize", 7);
    hold on
    semilogy(simParameters.SNRInVec,[resultsRX.CodedBER],"-s", "LineWidth", 1.5, "MarkerSize", 7);
    hold off
    legend("DeepRx (PyTorch)","Conventional 5G Rx", "Location", "southwest");
    grid on;
    xlabel('SNR (dB)');
    ylabel('Coded BER');
    
    % Plot throughput against SNR
    nexttile;
    plot(simParameters.SNRInVec,[resultsAIML.PercThroughput], "-*", "Color", co(5,:), "LineWidth", 1.5, "MarkerSize", 7);
    hold on
    plot(simParameters.SNRInVec,[resultsRX.PercThroughput], "-s" ,"LineWidth", 1.5, "MarkerSize", 7);
    hold off
    legend("DeepRx (PyTorch)", "Conventional 5G Rx", "Location", "southeast");
    grid on;
    xlabel('SNR (dB)');
    ylabel('Throughput (%)');
    
    % Add a title to the tiled layout summarizing the system configuration
    title(t,sprintf('DelaySpread: %.2e, MaxDopplerShift: %.2f, DMRS: %d / %d, Channel: %s',...
        simParameters.DelaySpread,simParameters.MaximumDopplerShift,...
        simParameters.DMRSAdditionalPosition,simParameters.DMRSConfigurationType,...
        simParameters.ChannelModel));
end

function [resultsRX, resultsTORCH] = evaluateLinkPerformance(simParameters, model)
% -----------------------------------------------------------------
% Initialize simulation parameters
% -----------------------------------------------------------------
simParameters.TrainNow         = false;
simParameters.DisplayInfo      = true;
randParameters.DelaySpread     = simParameters.DelaySpread;
randParameters.MaxDopplerShift = simParameters.MaximumDopplerShift;
randParameters.DMRSAddPos      = simParameters.DMRSAdditionalPosition;
randParameters.DMRSConfigType  = simParameters.DMRSConfigurationType;
randParameters.ChannelModel    = simParameters.ChannelModel;
numOutputArgs = nargout('hGetFeaturesAndLabels');

% Check if the Python execution mode is 'InProcess' with parallelism enabled
if strcmp(simParameters.PythonExecutionMode, "InProcess") && simParameters.UseParallel
    error("Python execution mode must be 'OutOfProcess' when `UseParallel` is true.")
end

% Preallocate the results structures
resultsTORCH(1:length(simParameters.SNRInVec)) = struct('SNRIn', -1, 'BLER', -1, 'UncodedBER', -1, 'CodedBER', -1, ...
    'SimThroughput', -1, 'MaxThroughput', -1, 'PercThroughput', -1);
resultsRX(1:length(simParameters.SNRInVec)) = struct('SNRIn', -1, 'BLER', -1, 'UncodedBER', -1, 'CodedBER', -1, ...
    'SimThroughput', -1, 'MaxThroughput', -1, 'PercThroughput', -1);

% -----------------------------------------------------------------
% Setup parallel computing if enabled
% -----------------------------------------------------------------
if simParameters.UseParallel && canUseParallelPool
    curPool = gcp;
    fprintf('\n- Test data generation: CPU acceleration on (%d) workers\n', curPool.NumWorkers);
else
    fprintf('\n- Test data generation: Serial execution\n');
end
% Inference/prediction environment
device = pyrun(["import torch", "device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')"], "device");
fprintf('- Inference environment: %s\n', upper(string(device.type)));

% -----------------------------------------------------------------
% Simulate conventional and AI-native receivers using parallel execution
% -----------------------------------------------------------------
fprintf('\nSimulating DeepRx and conventional receivers for %d SNR points...\n', length(simParameters.SNRInVec));
if simParameters.UseParallel && canUseParallelPool
    futuresRX(1:length(simParameters.SNRInVec))    = parallel.FevalFuture;
    futuresTORCH(1:length(simParameters.SNRInVec)) = parallel.FevalFuture;
    
    % Ensure futures are canceled on function exit
    cleanupFuturesRX     = onCleanup(@() cancel(futuresRX));
    cleanupFuturesTORCH  = onCleanup(@() cancel(futuresTORCH));

    % Asynchronously simulate each SNR point
    for i = 1:length(simParameters.SNRInVec)
        randParameters.SNRIn = simParameters.SNRInVec(i);
        % Conventional 5G Receiver
        futuresRX(i) = parfeval(curPool, @hGetFeaturesAndLabels, numOutputArgs, simParameters, randParameters, Iteration=30e3 + i);

        % AI-Native Receiver (PyTorch)
        futuresTORCH(i) = parfeval(curPool, @hGetFeaturesAndLabels, numOutputArgs, simParameters, randParameters, Net=model, Iteration=30e3 + i);
    end
    
    % (Conventional Rx) Fetch the next finished results from a worker
    fprintf('\n');
    for i = 1:length(simParameters.SNRInVec)
        [completedIdxRX, tmpResultRX, ~, ~, ~] = fetchNext(futuresRX);
        resultsRX(:, completedIdxRX) = tmpResultRX;

        % (Conventional Rx) Update progress status
        if simParameters.DisplayInfo
            fprintf('5G Receiver    : (%6.2f%%) SNRIn: %+6.2f dB  |  Channel: %s  |  Delay Spread: %-7.2e  |  Max Doppler shift: %-6.2f | DMRS Add. Pos. / Config. Type: %d / %d\n', ...
                100 * i / length(simParameters.SNRInVec), tmpResultRX.SNRIn, randParameters.ChannelModel, randParameters.DelaySpread, randParameters.MaxDopplerShift, ...
                randParameters.DMRSAddPos, randParameters.DMRSConfigType);
        end

        % (AI-native Rx) Fetch the next finished results from a worker
        [completedIdxTORCH, tmpResultTORCH, ~, ~, ~] = fetchNext(futuresTORCH);
        resultsTORCH(:, completedIdxTORCH) = tmpResultTORCH;
    
        % (AI-native Rx) Update progress status
        if simParameters.DisplayInfo
            fprintf('PyTorch DeepRx : (%6.2f%%) SNRIn: %+6.2f dB  |  Channel: %s  |  Delay Spread: %-7.2e  |  Max Doppler shift: %-6.2f | DMRS Add. Pos. / Config. Type: %d / %d\n', ...
                100 * i / length(simParameters.SNRInVec), tmpResultTORCH.SNRIn, randParameters.ChannelModel, randParameters.DelaySpread, randParameters.MaxDopplerShift, ...
                randParameters.DMRSAddPos, randParameters.DMRSConfigType);
        end
    end

    % -----------------------------------------------------------------
    % Sort results based on SNR index
    % -----------------------------------------------------------------
    [~, idxRX]    = sort([resultsRX.SNRIn]);
    [~, idxTORCH] = sort([resultsTORCH.SNRIn]);
    resultsRX     = resultsRX(idxRX);
    resultsTORCH  = resultsTORCH(idxTORCH);
else % serial execution
    fprintf('\n');
    for i = 1:length(simParameters.SNRInVec)
        % Calculate the performance results for the conventional 5G
        % receiver and PyTorch AI-native receiver
        randParameters.SNRIn = simParameters.SNRInVec(i);        

        % Conventional 5G Receiver
        resultsRX(i) = hGetFeaturesAndLabels(simParameters, randParameters, Iteration=30e3+i);

        % AI-Native Receiver (PyTorch)
        resultsTORCH(i) = hGetFeaturesAndLabels(simParameters, randParameters, Net=model, Iteration=30e3+i);

        if simParameters.DisplayInfo
            fprintf('(%6.2f%%) SNRIn: %+6.2f dB  |  Channel: %s  |  Delay Spread: %-7.2e  |  Max Doppler shift: %-6.2f | DMRS Add. Pos. / Config. Type: %d / %d\n', ...
                100 * i / length(simParameters.SNRInVec), randParameters.SNRIn, randParameters.ChannelModel, randParameters.DelaySpread, randParameters.MaxDopplerShift, ...
                randParameters.DMRSAddPos, randParameters.DMRSConfigType);
        end
    end
end
end

References

[1] M. Honkala, D. Korpi, and J. M. J. Huttunen, "DeepRx: Fully Convolutional Deep Learning Receiver," in IEEE Transactions on Wireless Communications, vol. 20, no. 6, pp. 3925—3940, June 2021.

[2] He, K., Zhang, X., Ren, S., and Sun, J., "Identity mappings in deep residual networks", in European Conference on Computer Vision, pp. 630—645, Springer, 2016.

[3] F. Chollet, "Xception: Deep Learning with Depthwise Separable Convolutions," in 2017 IEEE Conference on Computer Vision and Pattern Recognition (CVPR), Honolulu, HI, USA, 2017 pp. 1800—1807.

See Also

Topics