【USRP】NVIDIA Sionna:用于 6G 物理层研究的开源库

目录

  • Sionna:用于 6G 物理层研究的开源库
  • 主要特点
    • 实现6G研究的民主化
    • 支持 5G、6G 等
    • 模块化、可扩展、可伸缩
    • 快速启动您的研究
  • 好处
    • 原生人工智能支持
    • 综合研究平台
    • 开放生态系统
  • 安装
    • 笔记
    • 使用 pip 安装
    • 基于Docker的安装
    • 从源代码安装
    • “你好世界!”
    • 探索锡奥纳 (Sionna)
      • 加载所需包
    • 首次链路级仿真
    • 建立端到端模型
    • 运行一些吞吐量测试(图形模式)
    • 误码率 (BER) 蒙特卡罗模拟
    • 结论

Sionna:用于 6G 物理层研究的开源库

Sionna ™是一个用于链路级仿真的 GPU 加速开源库。它能够快速构建复杂通信系统架构的原型,并为机器学习在 6G 信号处理中的集成提供原生支持。

Sionna ™ 是一个基于TensorFlow的开源库,用于模拟无线和光通信系统的物理层。复杂通信系统架构的快速原型设计就像连接所需的构建块一样简单,这些构建块以Keras层的形式提供。使用可微分层,梯度可以在整个系统中反向传播,这是系统优化和机器学习,尤其是神经网络集成的关键推动因素。NVIDIA GPU 加速提供了数量级更快的模拟,从而实现了对此类系统的交互式探索,例如,在可以在Google Colab等云服务上运行的Jupyter 笔记本中。如果没有可用的 GPU,Sionna 将在 CPU 上运行。

Sionna 由 NVIDIA 开发、不断扩展和使用,以推动 5G 和 6G 研究。它支持 MU-MIMO(多用户多输入多输出)链路级模拟设置,具有符合 5G 的代码,包括低密度奇偶校验 (LDPC) 和 Polar 编码/解码器、3GPP 信道模型、OFDM(正交频分复用)、信道估计、均衡和软解映射。还有许多其他组件可用,例如卷积码和 Turbo 码、用于模拟光纤信道的分步傅里叶方法以及用于研究单载波波形的滤波器和窗口。每个构建块都是一个独立的模块,可以根据您的需求轻松测试、理解和修改。

主要特点

实现6G研究的民主化

Sionna 实现了一系列经过精心测试的先进算法,可用于基准测试和端到端性能评估。这让您可以专注于研究,使其更具影响力和可重复性,同时减少花在实现专业领域之外的组件上的时间。Sionna 是下一代通信系统(如 6G)物理层研究的宝贵工具。

支持 5G、6G 等

Sionna 由 NVIDIA 开发、不断扩展和使用,用于推动 5G 和 6G 物理层研究。它支持越来越多的功能,例如使用符合 5G 标准的低密度奇偶校验 (LDPC) 和 Polar 码进行多用户多输入多输出 (MU-MIMO) 链路级模拟、3GPP TR38.901 信道模型和射线追踪、正交频分复用 (OFDM)、信道估计等。

模块化、可扩展、可伸缩

每个构建块都是一个独立的模块,您可以根据需要轻松测试、理解和修改。Sionna 提供高级 Python 应用程序编程接口 (API),可轻松建模复杂的通信系统,同时提供充分的灵活性以适应您的研究。基于 TensorFlow,Sionna 可自动跨多个 GPU 扩展。

快速启动您的研究

Sionna 附带大量文档,包括许多可帮助您尽快入门的教程。Sionna 开箱即用,支持 NVIDIA GPU,速度极快,非常适合通信领域的机器学习研究。

好处

原生人工智能支持

Sionna 是第一个完全可微分的链接级模拟器,它使神经网络的集成变得轻而易举。

综合研究平台

综合研究平台
Sionna 将链路级和通道模拟功能与原生机器学习和 GPU 支持相结合。

开放生态系统

Sionna 是基于 Python 的开源项目,欢迎第三方的贡献。

安装

Sionna 需要Python和Tensorflow。为了在您的机器上运行教程笔记本,您还需要JupyterLab 。您也可以在Google Colab上测试它们。虽然不是必需的,但我们建议在Docker 容器中运行 Sionna 。

笔记

Sionna 需要TensorFlow 2.13-2.15和 Python 3.8-3.11。我们推荐使用 Ubuntu 22.04。早期版本的 TensorFlow 可能仍能使用,但由于已知未修补的 CVE,因此不推荐使用。

要在 CPU 上运行光线追踪器,DrJit 需要LLVM 。请查看LLVM 后端的安装说明。光线追踪预览需要最新版本的JupyterLab 。您可以通过(需要重新启动JupyterLab)升级到最新版本。pip install --upgrade ipykernel jupyterlab

我们参考TensorFlow GPU 支持教程来了解 GPU 支持和所需的驱动程序设置。

使用 pip 安装

我们建议在虚拟环境中执行此操作,例如使用conda。在 macOS 上,您需要先安装tensorflow-macos。

1.)安装软件包

pip install sionna

2.)在 Python 中测试安装

python>>> import sionna
>>> print(sionna.__version__)
0.19.2

3.) 一旦安装了 Sionna,您就可以运行Sionna“Hello, World!”示例,查看快速入门指南或教程。

对于本地安装,可以使用JupyterLab Desktop应用程序。这直接包括 Python 的安装和配置。

基于Docker的安装

1.) 确保你的系统上安装了Docker 。在 Ubuntu 22.04 上,你可以运行例如

sudo apt install docker.io

确保您的用户属于docker组(请参阅Docker 安装后)。

sudo usermod -aG docker $USER

注销并重新登录以加载更新的群组成员资格。

为了在 Linux 上获得 GPU 支持,您需要安装NVIDIA Container Toolkit。

2.) 构建 Sionna Docker 映像。在 Sionna 目录中,运行:

make docker

3.) 运行支持 GPU 的 Docker 镜像

make run-docker gpus=all

或者不使用 GPU:

make run-docker

这将立即启动安装了 Sionna 的 Docker 映像,并在端口 8888 上运行 JupyterLab。

4.) 通过在浏览器中连接http://127.0.0.1:8888浏览示例笔记本。

从源代码安装

我们建议在虚拟环境中执行此操作,例如使用conda。

1.) 克隆此存储库并从其根文件夹中执行:

make install

2.)在 Python 中测试安装

python
>>> import sionna
>>> print(sionna.__version__)
0.19.2

“你好世界!”

导入 Sionna:

import os
if os.getenv("CUDA_VISIBLE_DEVICES") is None:gpu_num = 0 # Use "" to use the CPUos.environ["CUDA_VISIBLE_DEVICES"] = f"{gpu_num}"
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'# Import Sionna
try:import sionna
except ImportError as e:# Install Sionna if package is not already installedimport osos.system("pip install sionna")import sionna# IPython "magic function" for inline plots
%matplotlib inline
import matplotlib.pyplot as plt

让我们首先创建一个BinarySource来生成一批随机的位向量,我们可以将其映射到星座符号:

batch_size = 1000 # Number of symbols we want to generate
num_bits_per_symbol = 4 # 16-QAM has four bits per symbol
binary_source = sionna.utils.BinarySource()
b = binary_source([batch_size, num_bits_per_symbol])
b
<tf.Tensor:形状=(1000,4),dtype=float32,numpy=
数组([[0., 1., 0., 1.][0., 0., 1., 0.][1., 1., 0., 0.]...,[0., 0., 1., 0.][1., 0., 1., 1.][1., 0., 1., 1.]], dtype=float32)>

接下来,让我们创建一个星座并将其可视化:

constellation = sionna.mapping.Constellation("qam", num_bits_per_symbol)
constellation.show();

在这里插入图片描述
我们现在需要一个映射器,根据上面显示的位标记将 b 的每一行映射到星座符号。

mapper = sionna.mapping.Mapper(constellation=constellation)
x = mapper(b)
x[:10]
<tf.Tensor:形状=(10,1),dtype=complex64,numpy=
数组([[ 0.3162278-0.9486833j][0.9486833+0.3162278j][-0.3162278-0.3162278j][0.9486833+0.3162278j][0.9486833-0.9486833j][0.3162278+0.9486833j][0.9486833+0.9486833j][0.3162278+0.9486833j][0.3162278-0.3162278j][ 0.3162278 + 0.9486833j]], dtype=complex64)>

现在让我们让事情变得更有趣一点,通过AWGN 信道发送我们的符号:

awgn = sionna.channel.AWGN()
ebno_db = 15 # Desired Eb/No in dB
no = sionna.utils.ebnodb2no(ebno_db, num_bits_per_symbol, coderate=1)
y = awgn([x, no])# Visualize the received signal
import matplotlib.pyplot as plt
import numpy as npfig = plt.figure(figsize=(7,7))
ax = fig.add_subplot(111)
plt.scatter(np.real(y), np.imag(y));
ax.set_aspect("equal", adjustable="box")
plt.xlabel("Real Part")
plt.ylabel("Imaginary Part")
plt.grid(True, which="both", axis="both")
plt.title("Received Symbols");

在这里插入图片描述

探索锡奥纳 (Sionna)

本示例笔记本将引导您了解基本原理并说明Sionna的主要功能。只需几个命令,您就可以模拟许多符合 5G 标准的组件的 PHY 层链路级性能,包括轻松可视化结果。

加载所需包

必须安装Sionna python 包。

import os
if os.getenv("CUDA_VISIBLE_DEVICES") is None:gpu_num = 0 # Use "" to use the CPUos.environ["CUDA_VISIBLE_DEVICES"] = f"{gpu_num}"
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'# Import Sionna
try:import sionna
except ImportError as e:# Install Sionna if package is not already installedimport osos.system("pip install sionna")import sionnaimport numpy as np
import tensorflow as tf
# Avoid warnings from TensorFlow
tf.get_logger().setLevel('ERROR')# IPython "magic function" for inline plots
%matplotlib inline
import matplotlib.pyplot as plt

提示:您可以通过操作员在 Jupyter 中运行 bash 命令!。

!nvidia-smi
2024926 日星期四 14:40:00
+------------------------------------------------------------------------------------------------+
| NVIDIA-SMI 535.183.01 驱动程序版本:535.183.01 CUDA 版本:12.2 |
|----------------------------------------+----------------------+--------------------------------+
| GPU 名称 Persistence-M | Bus-Id Disp.A | 易失性 Uncorr. ECC |
| 风扇温度性能功率:使用情况/容量 | 内存使用情况 | GPU-Util 计算 M。|
| | | 米格 M. |
|=========================================+========================+======================|
| 0 NVIDIA GeForce RTX 3090 关闭 | 00000000:01:00.0 关闭 | N/A |
| 0% 48C P2 39W / 350W | 292MiB / 24576MiB | 0% 默认 |
| | | 不适用|
+----------------------------------------------------+----------------------+--------------------------------+
| 1 NVIDIA GeForce RTX 3090 关闭 | 00000000:4D:00.0 关闭 | N/A |
| 30% 42C P8 23W / 350W | 3MiB / 24576MiB | 0% 默认 |
| | | 不适用|
+----------------------------------------------------+----------------------+--------------------------------++------------------------------------------------------------------------------------------------+
| 流程: |
| GPU GI CI PID 类型 进程名称 GPU 内存 |
| ID ID使用情况 |
|=============================================================================================|
+------------------------------------------------------------------------------------------------+

如果有多个 GPU 可用,我们会将此笔记本限制为单 GPU 使用。如果只有一个 GPU 可用,则可以忽略此命令。

此外,我们希望避免此笔记本在初始化并设置memory_growth为活动状态时实例化整个 GPU 内存。

备注:Sionna 不需要 GPU。所有内容也可以在 CPU 上运行 - 但您可能需要等待一段时间。

# Configure the notebook to use only a single GPU and allocate only as much memory as needed
# For more details, see https://www.tensorflow.org/guide/gpu
gpus = tf.config.list_physical_devices('GPU')
print('Number of GPUs available :', len(gpus))
if gpus:gpu_num = 0 # Index of the GPU to be usedtry:#tf.config.set_visible_devices([], 'GPU')tf.config.set_visible_devices(gpus[gpu_num], 'GPU')print('Only GPU number', gpu_num, 'used.')tf.config.experimental.set_memory_growth(gpus[gpu_num], True)except RuntimeError as e:print(e)

Sionna 数据流和设计范式
Sionna 本质上通过批处理实现模拟并行化,即批处理维度中的每个元素都是独立模拟的。

这意味着第一个张量维度始终用于帧间并行化,类似于Matlab/NumPy 模拟中的外部for 循环。

为了保持数据流高效,Sionna 遵循一些简单的设计原则:

信号处理组件作为单独的Keras 层实现。

tf.float32分别用作首选数据类型和tf.complex64复值数据类型。这允许更简单地重复使用组件(例如,相同的置乱层可用于二进制输入和 LLR 值)。

模型可以在急切模式下开发,从而允许简单(且快速)地修改系统参数。

可以在更快的图形模式下执行数字运算模拟,甚至可以为大多数组件提供XLA加速。

只要有可能,组件就会通过自动分级自动区分,以简化深度学习设计流程。

代码被构建为用于不同任务的子包,例如通道编码、映射等(有关详细信息,请参阅API 文档)。

划分为单独的块简化了部署,并且所有层和功能都附带单元测试以确保其正确的行为。

这些范例简化了我们的组件在广泛的通信相关应用程序中的可重用性和可靠性。

关于随机数生成的注释
加载 Sionna 时,它会实例化Python、NumPy和TensorFlow的随机数生成器 (RNG) 。您可以选择设置一个种子,只要只使用这些 RNG,它就会使所有结果都具有确定性。在下面的单元格中,您可以看到如何设置此种子以及如何使用不同的 RNG。

sionna.config.seed = 40# Python RNG - use instead of
# import random
# random.randint(0, 10)
print(sionna.config.py_rng.randint(0,10))# NumPy RNG - use instead of
# import numpy as np
# np.random.randint(0, 10)
print(sionna.config.np_rng.integers(0,10))# TensorFlow RNG - use instead of
# import tensorflow as tf
# tf.random.uniform(shape=[1], minval=0, maxval=10, dtype=tf.int32)
print(sionna.config.tf_rng.uniform(shape=[1], minval=0, maxval=10, dtype=tf.int32))
7
5
tf.Tensor([2],形状=(1,),dtype=int32)

让我们开始吧 - 第一层(Eager 模式)
每一层都需要初始化一次才能使用。

提示:使用API 文档查找所有现有组件的概述。

我们现在想通过 AWGN 信道传输一些符号。首先,我们需要初始化相应的层。

channel = sionna.channel.AWGN() # init AWGN channel layer

在第一个例子中,我们想要将高斯噪声添加到某些给定值中x。

记住 - 第一个维度是批次维度。

我们模拟 2 个消息帧,每个帧包含 4 个符号。

备注:AWGN信道定义为复值。

# define a (complex-valued) tensor to be transmitted
x = tf.constant([[0., 1.5, 1., 0.],[-1., 0., -2, 3 ]], dtype=tf.complex64)# let's have look at the shape
print("Shape of x: ", x.shape)
print("Values of x: ", x)
x 的形状:(2,4)
x 的值:tf.Tensor(
[[ 0.+0.j 1.5+0.j 1.+0.j 0.+0.j][-1. +0.j 0. +0.j -2. +0.j 3. +0.j]], shape=(2, 4), dtype=complex64)

我们希望模拟信噪比为 5 dB 的信道。为此,我们可以简单地调用之前定义的层channel。

如果您从未使用过Keras,那么您可以将层视为一个函数:它有一个输入并返回处理后的输出。

备注:每次执行此单元时都会绘制一个新的噪声实现。

ebno_db = 5# calculate noise variance from given EbNo
no = sionna.utils.ebnodb2no(ebno_db = ebno_db,num_bits_per_symbol=2, # QPSKcoderate=1)
y = channel([x, no])print("Noisy symbols are: ", y)
噪声符号为:tf.Tensor(
[[-0.02095131+0.19480924j 1.3121496 +0.05868753j 0.67274046-0.13089974j-0.303877 +0.19657521j][-0.9967893 +0.12435442j -0.5632028 -0.14088595j -1.9711018 -0.3130482j2.7371373 +0.26847288j]],形状=(2,4),dtype=complex64)

批次和多维张量
Sionna 原生支持多维张量。

大多数层在最后一个维度上运行,并且可以具有任意输入形状(在输出时保留)。

假设我们想为长度为 500 的 64 个代码字添加 CRC-24 校验(例如,每个子载波不同的 CRC)。此外,我们想在一批 100 个样本上并行化模拟。

batch_size = 100 # outer level of parallelism
num_codewords = 64 # codewords per batch sample
info_bit_length = 500 # info bits PER codewordsource = sionna.utils.BinarySource() # yields random bitsu = source([batch_size, num_codewords, info_bit_length]) # call the source layer
print("Shape of u: ", u.shape)# initialize an CRC encoder with the standard compliant "CRC24A" polynomial
encoder_crc = sionna.fec.crc.CRCEncoder("CRC24A")
decoder_crc = sionna.fec.crc.CRCDecoder(encoder_crc) # connect to encoder# add the CRC to the information bits u
c = encoder_crc(u) # returns a list [c, crc_valid]
print("Shape of c: ", c.shape)
print("Processed bits: ", np.size(c.numpy()))# we can also verify the results
# returns list of [info bits without CRC bits, indicator if CRC holds]
u_hat, crc_valid = decoder_crc(c)
print("Shape of u_hat: ", u_hat.shape)
print("Shape of crc_valid: ", crc_valid.shape)print("Valid CRC check of first codeword: ", crc_valid.numpy()[0,0,0])
u 的形状:(100,64,500)
c 的形状:(100,64,524)
已处理位数:3353600
u_hat 的形状:(100、64、500)
crc_valid 的形状:(100,64,1)
第一个代码字的有效 CRC 校验:真

我们想做另一个模拟,但针对 5 个独立用户。

我们不需要定义 5 个不同的张量,只需添加另一个维度即可。

num_users = 5u = source([batch_size, num_users, num_codewords, info_bit_length])
print("New shape of u: ", u.shape)# We can re-use the same encoder as before
c = encoder_crc(u)
print("New shape of c: ", c.shape)
print("Processed bits: ", np.size(c.numpy()))
u 的新形状:(100, 5, 64, 500)
c 的新形状:(100,5,64,524)
已处理位数:16768000

良好的结果可视化往往有助于获得新的研究思路。因此,Sionna 具有内置的绘图功能。

让我们看一下16-QAM星座。

constellation = sionna.mapping.Constellation("qam", num_bits_per_symbol=4)
constellation.show();

在这里插入图片描述

首次链路级仿真

我们已经可以用几个简单的命令来构建强大的代码。

如前所述,Sionna 旨在将系统复杂性隐藏到 Keras 层中。但是,我们仍然希望提供尽可能多的灵活性。因此,大多数层都有几种初始参数选择,但通常默认选择是一个好的开始。

提示:API 文档提供了许多有用的参考和实现细节。

# system parameters
n_ldpc = 500 # LDPC codeword length
k_ldpc = 250 # number of info bits per LDPC codeword
coderate = k_ldpc / n_ldpc
num_bits_per_symbol = 4 # number of bits mapped to one symbol (cf. QAM)

通常,会实现几种不同的算法,例如,解映射器支持“true app”解映射,也支持“max-log”解映射。

LDPC BP译码器的校验节点(CN)更新功能也支持多种算法。

demapping_method = "app" # try "max-log"
ldpc_cn_type = "boxplus" # try also "minsum"

让我们根据给定的系统参数初始化所有必需的组件。

binary_source = sionna.utils.BinarySource()
encoder = sionna.fec.ldpc.encoding.LDPC5GEncoder(k_ldpc, n_ldpc)
constellation = sionna.mapping.Constellation("qam", num_bits_per_symbol)
mapper = sionna.mapping.Mapper(constellation=constellation)
channel = sionna.channel.AWGN()
demapper = sionna.mapping.Demapper(demapping_method,constellation=constellation)
decoder = sionna.fec.ldpc.decoding.LDPC5GDecoder(encoder,hard_out=True, cn_type=ldpc_cn_type,num_iter=20)

我们现在可以在Eager 模式下运行代码。这允许我们随时修改结构 - 您可以尝试不同的batch_size或不同的 SNR ebno_db。

# simulation parameters
batch_size = 1000
ebno_db = 4# Generate a batch of random bit vectors
b = binary_source([batch_size, k_ldpc])# Encode the bits using 5G LDPC code
print("Shape before encoding: ", b.shape)
c = encoder(b)
print("Shape after encoding: ", c.shape)# Map bits to constellation symbols
x = mapper(c)
print("Shape after mapping: ", x.shape)# Transmit over an AWGN channel at SNR 'ebno_db'
no = sionna.utils.ebnodb2no(ebno_db, num_bits_per_symbol, coderate)
y = channel([x, no])
print("Shape after channel: ", y.shape)# Demap to LLRs
llr = demapper([y, no])
print("Shape after demapping: ", llr.shape)# LDPC decoding using 20 BP iterations
b_hat = decoder(llr)
print("Shape after decoding: ", b_hat.shape)# calculate BERs
c_hat = tf.cast(tf.less(0.0, llr), tf.float32) # hard-decided bits before dec.
ber_uncoded = sionna.utils.metrics.compute_ber(c, c_hat)ber_coded = sionna.utils.metrics.compute_ber(b, b_hat)print("BER uncoded = {:.3f} at EbNo = {:.1f} dB".format(ber_uncoded, ebno_db))
print("BER after decoding = {:.3f} at EbNo = {:.1f} dB".format(ber_coded, ebno_db))
print("In total {} bits were simulated".format(np.size(b.numpy())))
编码前形状:(1000,250)
编码后的形状:(1000,500)
映射后的形状:(1000,125)
通道后的形状:(1000,125)
解映射后的形状:(1000,500)
解码后形状:(1000,250)
未编码 BER = 0.119,EbNo = 4.0 dB
解码后 BER = 0.008,EbNo = 4.0 dB
总共模拟了 250000

总结一下:我们模拟了 250,000 比特的传输,包括高阶调制和信道编码!

但是我们可以通过TF 图形执行甚至更快地完成任务!

建立端到端模型

我们现在定义一个更方便训练和蒙特卡洛模拟的Keras 模型。

我们模拟了时变多径信道( 3GPP TR38.901 中的TDL-A模型)上的传输。为此,我们使用了 OFDM 和具有高阶调制的传统比特交织编码调制 (BICM) 方案。信息比特受 5G 兼容 LDPC 码保护。

备注:由于参数数量较多,我们将其定义为字典。

class e2e_model(tf.keras.Model): # inherits from keras.model"""Example model for end-to-end link-level simulations.Parameters----------params: dictA dictionary defining the system parameters.Input-----batch_size: int or tf.intThe batch_sizeused for the simulation.ebno_db: float or tf.floatA float defining the simulation SNR.Output------(b, b_hat):Tuple:b: tf.float32A tensor of shape `[batch_size, k]` containing the transmittedinformation bits.b_hat: tf.float32A tensor of shape `[batch_size, k]` containing the receiver'sestimate of the transmitted information bits."""def __init__(self,params):super().__init__()# Define an OFDM Resource Grid Objectself.rg = sionna.ofdm.ResourceGrid(num_ofdm_symbols=params["num_ofdm_symbols"],fft_size=params["fft_size"],subcarrier_spacing=params["subcarrier_spacing"],num_tx=1,num_streams_per_tx=1,cyclic_prefix_length=params["cyclic_prefix_length"],pilot_pattern="kronecker",pilot_ofdm_symbol_indices=params["pilot_ofdm_symbol_indices"])# Create a Stream Management objectself.sm = sionna.mimo.StreamManagement(rx_tx_association=np.array([[1]]),num_streams_per_tx=1)self.coderate = params["coderate"]self.num_bits_per_symbol = params["num_bits_per_symbol"]self.n = int(self.rg.num_data_symbols*self.num_bits_per_symbol)self.k = int(self.n*coderate)# Init layersself.binary_source = sionna.utils.BinarySource()self.encoder = sionna.fec.ldpc.encoding.LDPC5GEncoder(self.k, self.n)self.interleaver = sionna.fec.interleaving.RowColumnInterleaver(row_depth=self.num_bits_per_symbol)self.deinterleaver = sionna.fec.interleaving.Deinterleaver(self.interleaver)self.mapper = sionna.mapping.Mapper("qam", self.num_bits_per_symbol)self.rg_mapper = sionna.ofdm.ResourceGridMapper(self.rg)self.tdl = sionna.channel.tr38901.TDL(model="A",delay_spread=params["delay_spread"],carrier_frequency=params["carrier_frequency"],min_speed=params["min_speed"],max_speed=params["max_speed"])self.channel = sionna.channel.OFDMChannel(self.tdl, self.rg, add_awgn=True, normalize_channel=True)self.ls_est = sionna.ofdm.LSChannelEstimator(self.rg, interpolation_type="nn")self.lmmse_equ = sionna.ofdm.LMMSEEqualizer(self.rg, self.sm)self.demapper = sionna.mapping.Demapper(params["demapping_method"],"qam", self.num_bits_per_symbol)self.decoder = sionna.fec.ldpc.decoding.LDPC5GDecoder(self.encoder,hard_out=True,cn_type=params["cn_type"],num_iter=params["bp_iter"])print("Number of pilots: {}".format(self.rg.num_pilot_symbols))print("Number of data symbols: {}".format(self.rg.num_data_symbols))print("Number of resource elements: {}".format(self.rg.num_resource_elements))print("Pilot overhead: {:.2f}%".format(self.rg.num_pilot_symbols /self.rg.num_resource_elements*100))print("Cyclic prefix overhead: {:.2f}%".format(params["cyclic_prefix_length"] /(params["cyclic_prefix_length"]+params["fft_size"])*100))print("Each frame contains {} information bits".format(self.k))def call(self, batch_size, ebno_db):# Generate a batch of random bit vectors# We need two dummy dimension representing the number of# transmitters and streams per transmitter, respectively.b = self.binary_source([batch_size, 1, 1, self.k])# Encode the bits using the all-zero dummy encoderc = self.encoder(b)# Interleave the bits before mapping (BICM)c_int = self.interleaver(c)# Map bits to constellation symbolss = self.mapper(c_int)# Map symbols onto OFDM ressource gridx_rg = self.rg_mapper(s)# Transmit over noisy multi-path channelno = sionna.utils.ebnodb2no(ebno_db, self.num_bits_per_symbol, self.coderate, self.rg)y = self.channel([x_rg, no])# LS Channel estimation with nearest pilot interpolationh_hat, err_var = self.ls_est ([y, no])# LMMSE Equalizationx_hat, no_eff = self.lmmse_equ([y, h_hat, err_var, no])# Demap to LLRsllr = self.demapper([x_hat, no_eff])# Deinterleave before decodingllr_int = self.deinterleaver(llr)# Decodeb_hat = self.decoder(llr_int)# number of simulated bitsnb_bits = batch_size*self.k# transmitted bits and the receiver's estimate after decodingreturn b, b_hat

让我们将模拟的系统参数定义为字典:

sys_params = {# Channel"carrier_frequency" : 3.5e9,"delay_spread" : 100e-9,"min_speed" : 3,"max_speed" : 3,"tdl_model" : "A",# OFDM"fft_size" : 256,"subcarrier_spacing" : 30e3,"num_ofdm_symbols" : 14,"cyclic_prefix_length" : 16,"pilot_ofdm_symbol_indices" : [2, 11],# Code & Modulation"coderate" : 0.5,"num_bits_per_symbol" : 4,"demapping_method" : "app","cn_type" : "boxplus","bp_iter" : 20
}

…并初始化模型:

model = e2e_model(sys_params)
飞行员人数:512
数据符号数:3072
资源元素数量:3584
飞行员开销:14.29%
循环前缀开销:5.88%
每帧包含6144个信息位

与以前一样,我们可以简单地调用模型来模拟给定模拟参数的 BER。

#simulation parameters
ebno_db = 10
batch_size = 200# and call the model
b, b_hat = model(batch_size, ebno_db)ber = sionna.utils.metrics.compute_ber(b, b_hat)
nb_bits = np.size(b.numpy())print("BER: {:.4} at Eb/No of {} dB and {} simulated bits".format(ber.numpy(), ebno_db, nb_bits))
BER:Eb/No 为 10 dB 且模拟比特数为 1228800 时为 0.001245

运行一些吞吐量测试(图形模式)

Sionna 不仅是一个易于使用的库,而且速度非常快。让我们测量一下上面定义的模型的吞吐量。

我们比较了eager和graph执行模式(详情请参阅Tensorflow 文档),以及XLA 的 eager(请参阅https://www.tensorflow.org/xla#enable_xla_for_tensorflow_models)。请注意,我们需要激活sionna.config.xla_compat功能才能使 XLA 正常工作。

提示:更改batch_size以查看批处理并行性如何提高吞吐量。根据您的机器,batch_size可能太大。

import time # this block requires the timeit librarybatch_size = 200
ebno_db = 5 # evalaute SNR point
repetitions = 4 # throughput is averaged over multiple runsdef get_throughput(batch_size, ebno_db, model, repetitions=1):""" Simulate throughput in bit/s per ebno_db point.The results are average over `repetition` trials.Input-----batch_size: int or tf.int32Batch-size for evaluation.ebno_db: float or tf.float32A tensor containing the SNR points be evaluatedmodel:Function or model that yields the transmitted bits `u` and thereceiver's estimate `u_hat` for a given ``batch_size`` and``ebno_db``.repetitions: intAn integer defining how many trails of the throughputsimulation are averaged."""# call model once to be sure it is compile properly# otherwise time to build graph is measured as well.u, u_hat = model(tf.constant(batch_size, tf.int32),tf.constant(ebno_db, tf.float32))t_start = time.perf_counter()# average over multiple runsfor _ in range(repetitions):u, u_hat = model(tf.constant(batch_size, tf.int32),tf.constant(ebno_db, tf. float32))t_stop = time.perf_counter()# throughput in bit/sthroughput = np.size(u.numpy())*repetitions / (t_stop - t_start)return throughput# eager mode - just call the model
def run_eager(batch_size, ebno_db):return model(batch_size, ebno_db)time_eager = get_throughput(batch_size, ebno_db, run_eager, repetitions=4)# the decorator "@tf.function" enables the graph mode
@tf.function
def run_graph(batch_size, ebno_db):return model(batch_size, ebno_db)time_graph = get_throughput(batch_size, ebno_db, run_graph, repetitions=4)# the decorator "@tf.function(jit_compile=True)" enables the graph mode with XLA
# we need to activate the sionna.config.xla_compat feature for this to work
sionna.config.xla_compat=True
@tf.function(jit_compile=True)
def run_graph_xla(batch_size, ebno_db):return model(batch_size, ebno_db)time_graph_xla = get_throughput(batch_size, ebno_db, run_graph_xla, repetitions=4)
# we deactivate the sionna.config.xla_compat so that the cell can be run mutiple times
sionna.config.xla_compat=Falseprint(f"Throughput in eager execution: {time_eager/1e6:.2f} Mb/s")
print(f"Throughput in graph execution: {time_graph/1e6:.2f} Mb/s")
print(f"Throughput in graph execution with XLA: {time_graph_xla/1e6:.2f} Mb/s")
XLA 可能导致数值精度降低。请谨慎使用。
Eager Execution 吞吐量:1.56 Mb/s
图形执行吞吐量:7.76 Mb/s
XLA 图形执行的吞吐量:57.66 Mb/s

显然,图形执行(使用 XLA)可产生更高的吞吐量(至少如果有快速 GPU 可用)。因此,对于详尽训练和蒙特卡罗模拟,图形模式(使用 XLA 和 GPU 加速)是首选。

误码率 (BER) 蒙特卡罗模拟

蒙特卡罗模拟在当今的通信研究和开发中无处不在。由于其高性能实现,Sionna 可直接用于模拟 BER,其性能可与编译语言相媲美 - 但仍然保持了脚本语言的灵活性。

ebno_dbs = np.arange(0, 15, 1.)
batch_size = 200 # reduce in case you receive an out-of-memory (OOM) errormax_mc_iter = 1000 # max number of Monte-Carlo iterations before going to next SNR point
num_target_block_errors = 500 # continue with next SNR point after target number of block errors# we use the built-in ber simulator function from Sionna which uses and early stop after reaching num_target_errors
sionna.config.xla_compat=True
ber_mc,_ = sionna.utils.sim_ber(run_graph_xla, # you can also evaluate the model directlyebno_dbs,batch_size=batch_size,num_target_block_errors=num_target_block_errors,max_mc_iter=max_mc_iter,verbose=True) # print status and summary
sionna.config.xla_compat=False
XLA 可能导致数值精度降低。请谨慎使用。
EbNo [dB] | BER | BLER | 比特错误 | 比特数 | 块错误 | 块数 | 运行时间 [s] | 状态
-------------------------------------------------------------------------------------------------------------------------------------------0.0 | 3.4352e-01 | 1.0000e+00 | 1266347 | 3686400 | 600 | 600 | 0.1 |达到目标块错误1.0 | 3.2095e-01 | 1.0000e+00 | 1183166 | 3686400 | 600 | 600 | 0.1 |达到目标块错误2.0 | 2.9738e-01 | 1.0000e+00 | 1096268 | 3686400 | 600 | 600 | 0.1 |达到目标块错误3.0 | 2.7369e-01 | 1.0000e+00 | 1008918 | 3686400 | 600 | 600 | 0.1 |达到目标块错误4.0 | 2.4703e-01 | 1.0000e+00 | 910649 | 3686400 | 600 | 600 | 0.1 |达到目标块错误5.0 | 2.1839e-01 | 1.0000e+00 | 805067 | 3686400 | 600 | 600 | 0.1 |达到目标块错误6.0 | 1.8570e-01 | 1.0000e+00 | 684560 | 3686400 | 600 | 600 | 0.1 |达到目标块错误7.0 | 1.1760e-01 | 9.9167e-01 | 433539 | 3686400 | 595 | 600 | 0.1 |达到目标块错误8.0 | 4.2571e-02 | 4.7833e-01 | 313870 | 7372800 | 574 | 1200 | 0.2 |达到目标块错误9.0 | 1.3462e-02 | 1.5206e-01 | 281220 | 20889600 | 517 | 3400 | 0.4 |达到目标块错误10.0 | 3.3929e-03 | 3.5352e-02 | 296011 | 87244800 | 502 | 14200 | 1.8 |达到目标块错误11.0 | 8.4720e-04 | 9.1758e-03 | 284203 | 335462400 | 501 | 54600 | 6.8 |达到目标块错误12.0 | 2.7327e-04 | 2.9002e-03 | 289455 | 1059225600 | 500 | 172400 | 21.3 |达到目标块错误13.0 | 8.8057e-05 | 8.9500e-04 | 108205 | 1228800000 | 179 | 200000 | 24.5 |已达到最大迭代次数14.0 | 3.4128e-05 | 3.3500e-04 | 41936 | 1228800000 | 67 | 200000 | 24.5 |已达到最大迭代次数

我们来看看结果。

sionna.utils.plotting.plot_ber(ebno_dbs,ber_mc,legend="E2E Model",ylabel="Coded BER");

在这里插入图片描述

结论

我们希望您对 Sionna 感到兴奋——还有更多的东西有待发现:

TensorBoard 调试可用

扩展到多 GPU 模拟很简单

请参阅可用的教程以获取更多高级示例。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/27889.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大模型开发(四):PET项目——新零售决策评价系统(上)

PET项目——新零售决策评价系统&#xff08;上&#xff09; 0 前言1 项目介绍1.1 PET简介1.2 项目背景1.3 项目结构1.4 硬件配置 2 数据处理2.1 数据介绍2.2 提示词模板与标签映射2.3 BERT模型的输入格式2.4 硬模板类2.5 函数式编程2.6 datasets模块主要功能&#xff1a;在本项…

C语⾔数据类型和变量

C 语言的数据类型 类型分类&#xff1a; C 语言提供丰富的数据类型&#xff0c;包括字符型&#xff08;char、signed char、unsigned char&#xff09;、整型&#xff08;short、int、long 等多种&#xff0c;且各有 signed 和 unsigned 修饰形式&#xff09; 、浮点型&#x…

yum源选要配置华为云的源,阿里云用不了的情况

curl -O /etc/yum.repos.d/CentOS-Base.repo https://repo.huaweicloud.com/repository/conf/CentOS-7-reg.repo

JDBC连接数据库(MySQL)教程(包含可能出错的问题)

阅读提示&#xff1a;这篇文章关于Mysql的知识涉及到的不是很多&#xff0c;如果有需要我改天专门写一篇详细的关于mysql的文章&#xff0c;当然点进来的人大部分肯定是了解过mysql的。 一、准备工作&#xff08;驱动包&#xff09; 1.1 下载IntelliJ IDEA&#xff08;主要用…

详细分析KeepAlive的基本知识 并缓存路由(附Demo)

目录 前言1. 基本知识2. Demo2.1 基本2.2 拓展2.3 终极 3. 实战 前言 &#x1f91f; 找工作&#xff0c;来万码优才&#xff1a;&#x1f449; #小程序://万码优才/r6rqmzDaXpYkJZF 基本知识推荐阅读&#xff1a;KeepAlive知识点 从实战中学习&#xff0c;源自实战中vue路由的…

AI编程,常见的AI编程工具有哪些?如何用AI编程做一个简单的小软件?

随着AI的快速发展&#xff0c;编程不再是专业程序员的专属技能&#xff0c;而逐渐成为一种普通人也能掌握的工具。 如今&#xff0c;即使没有编程基础&#xff0c;也可以通过几种方式轻松入门AI编程&#xff0c;包括直接使用大语言模型进行编程、借助特定的AI软件进行可视化编程…

探秘 Linux 系统编程:进程地址空间的奇妙世界

亲爱的读者朋友们&#x1f603;&#xff0c;此文开启知识盛宴与思想碰撞&#x1f389;。 快来参与讨论&#x1f4ac;&#xff0c;点赞&#x1f44d;、收藏⭐、分享&#x1f4e4;&#xff0c;共创活力社区。 在 Linux 系统编程的领域里&#xff0c;进程地址空间可是个相当重要的…

2025-03-04 学习记录--C/C++-PTA 习题5-5 使用函数统计指定数字的个数

合抱之木&#xff0c;生于毫末&#xff1b;九层之台&#xff0c;起于累土&#xff1b;千里之行&#xff0c;始于足下。&#x1f4aa;&#x1f3fb; 一、题目描述 ⭐️ 二、代码&#xff08;C语言&#xff09;⭐️ #include <stdio.h>int CountDigit( int number, int di…

25年第四本【认知觉醒】

《认知觉醒》&#xff1a;一场与大脑的深度谈判 在信息爆炸的焦虑时代&#xff0c;我们像被抛入湍流的溺水者&#xff0c;拼命抓取各种自我提升的浮木&#xff0c;却在知识的漩涡中越陷越深。这不是一本简单的成功学指南&#xff0c;而是一场关于人类认知系统的深度对话&#…

汽车视频智能包装创作解决方案,让旅途记忆一键升级为影视级大片

在智能汽车时代&#xff0c;行车记录已不再是简单的影像留存&#xff0c;而是承载情感与创意的载体。美摄科技依托20余年视音频领域技术积累&#xff0c;推出汽车视频智能包装创作解决方案&#xff0c;以AI驱动影像处理与艺术创作&#xff0c;重新定义车载视频体验&#xff0c;…

DeepSeek 智慧城市应用:交通流量预测(918)

**摘要&#xff1a;**本文探讨了利用 DeepSeek 技术框架解决城市交通流量预测问题的方法&#xff0c;主要内容包括基于时空图卷积网络&#xff08;ST - GCN&#xff09;的预测模型、多传感器数据融合策略以及实时推理 API 服务的搭建&#xff0c;旨在为智慧城市的交通管理提供高…

如何在随机振动分析中包括缓冲器

总结 在随机振动分析中&#xff0c;准确模拟系统的动态行为对于预测其在随机激励下的响应至关重要。在这种情况下&#xff0c;分立阻尼器&#xff08;如减振器&#xff09;是必不可少的组件&#xff0c;因为它有助于模拟实际系统中的能量耗散机制。通过将离散阻尼器集成到模型…

python3.13安装教程【2025】python3.13超详细图文教程(包含安装包)

文章目录 前言一、python3.13安装包下载二、Python 3.13安装步骤三、Python3.13验证 前言 本教程将为你详细介绍 Python 3.13 python3.13安装教程&#xff0c;帮助你顺利搭建起 Python 3.13 开发环境&#xff0c;快速投身于 Python 编程的精彩实践中。 一、python3.13安装包下…

Transformer 代码剖析6 - 位置编码 (pytorch实现)

一、位置编码的数学原理与设计思想 1.1 核心公式解析 位置编码采用正弦余弦交替编码方案&#xff1a; P E ( p o s , 2 i ) sin ⁡ ( p o s 1000 0 2 i / d m o d e l ) P E ( p o s , 2 i 1 ) cos ⁡ ( p o s 1000 0 2 i / d m o d e l ) PE_{(pos,2i)} \sin\left(\fra…

CF 452A.Eevee(Java实现)

题目分析 输入一个数字-长度&#xff0c;输入一个字符串。判断这个字符串是具体的哪一个单词 思路分析 首先给了长度&#xff0c;那我先判断长度相同的单词&#xff0c;然后再一一对比&#xff0c;如果都能通过&#xff0c;那就输出这个单词 代码 import java.util.*;public …

【监控】使用Prometheus+Grafana搭建服务器运维监控面板(含带BearerToken的Exporter配置)

【监控】使用PrometheusGrafana搭建服务器运维监控面板&#xff08;含带BearerToken的Exporter配置&#xff09; 文章目录 1、Grafana 数据可视化面板2、Prometheus - 收集和存储指标数据3、Exporter - 采集和上报指标数据 1、Grafana 数据可视化面板 Grafana 是一个开源的可视…

ADC采集模块与MCU内置ADC性能对比

2.5V基准电压源&#xff1a; 1. 精度更高&#xff0c;误差更小 ADR03B 具有 0.1% 或更小的初始精度&#xff0c;而 电阻分压方式的误差主要来自电阻的容差&#xff08;通常 1% 或 0.5%&#xff09;。长期稳定性更好&#xff0c;分压电阻容易受到温度、老化的影响&#xff0c;长…

UDP协议(20250303)

1. UDP UDP:用户数据报协议&#xff08;User Datagram Protocol&#xff09;&#xff0c;传输层协议之一&#xff08;UDP&#xff0c;TCP&#xff09; 2. 特性 发送数据时不需要建立链接&#xff0c;节省资源开销不安全不可靠的协议 //一般用在实时性比较高…

基于https虚拟主机配置

一、https介绍 http 明文&#xff0c;80/tcp https 密文&#xff0c;443/tcp 二、安全性保障 1、数据安全性 数据加密 2、数据完整性 3、验证身份的真实性、有效性 三、数据安全性 手段&#xff1a;加密 发送方加密数据&#xff0c;接收方解密数据 对称加密算法 加密、解密数据…

机器学习(五)

一&#xff0c;多类&#xff08;Multiclass&#xff09; 多类是指输出不止有两个输出标签&#xff0c;想要对多个种类进行分类。 Softmax回归算法&#xff1a; Softmax回归算法是Logistic回归在多类问题上的推广&#xff0c;和线性回归一样&#xff0c;将输入的特征与权重进行…