当前位置: 首页 > news >正文

【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 模拟很简单

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

相关文章:

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

目录 Sionna&#xff1a;用于 6G 物理层研究的开源库主要特点实现6G研究的民主化支持 5G、6G 等模块化、可扩展、可伸缩快速启动您的研究 好处原生人工智能支持综合研究平台开放生态系统 安装笔记使用 pip 安装基于Docker的安装从源代码安装“你好世界&#xff01;”探索锡奥纳…...

DeepSeek开源周Day6:DeepSeek V3、R1 推理系统深度解析,技术突破与行业启示

DeepSeek 在开源周第六天再次发文&#xff0c;中文原文、官方号在知乎 DeepSeek - 知乎DeepSeek-V3 / R1 推理系统概览 - 知乎deepseek-ai/open-infra-index: Production-tested AI infrastructure tools for efficient AGI development and community-driven innovation 引言 …...

intra-mart实现logicDesigner与forma联动

一、前言 有一个需求&#xff0c;想实现从页面上传一个excel文件&#xff0c;点击提交&#xff0c;就转发给forma模块&#xff0c;然后用户在forma模块里&#xff0c;确认下自动填写的信息是否正确&#xff0c;正确的话就点击保存&#xff0c;存入数据库&#xff1b;不正确的话…...

《大语言模型的原理发展与应用》:此文为AI自动生成

《大语言模型的原理发展与应用》&#xff1a;此文为AI自动生成 一、引言&#xff1a;大语言模型&#xff0c;AI 时代的 “新引擎” 在当今数字化浪潮中&#xff0c;大语言模型宛如一颗璀璨的明星&#xff0c;照亮了人工智能发展的道路&#xff0c;成为推动各领域变革的核心驱…...

生态安全相关

概念&#xff1a;生态安全指一个国家具有支撑国家生存发展的较为完整、不受威胁的生态系统&#xff0c;以及应对内外重大生态问题的能力。 &#xff08;1&#xff09;国外生态安全的研究进展 国际上对生态安全的研究是从“环境”与“安全”之间的关系展开的。开始的阶段&#x…...

DeepSeek-R1国产化系统gpu驱动+cuda+ollama+webui可视化离线私有化部署

1.概述 网上大部分教程都是在线部署&#xff0c;完全离线私有化部署的文章不多&#xff0c;本文介绍从GPU驱动、cuda、ollama、deepseek模型和open webui等完全离线安装几个方面&#xff0c;让小白0基础也可以私有化部署大模型deepseek-R1。 我使用的设备是银河麒麟V10操作系统…...

数据集/API 笔记:新加坡风速 API

data.gov.sg 数据范围&#xff1a;2016年12月 - 2025年3月 API 查询方式 curl --request GET \--url https://api-open.data.gov.sg/v2/real-time/api/wind-speedcurl --request GET \--url "https://api-open.data.gov.sg/v2/real-time/api/wind-speed?date2024-07-16…...

transformer架构解析{掩码,(自)注意力机制,多头(自)注意力机制}(含代码)-3

目录 前言 掩码张量 什么是掩码张量 掩码张量的作用 生成掩码张量实现 注意力机制 学习目标 注意力计算规则 注意力和自注意力 注意力机制 注意力机制计算规则的代码实现 多头注意力机制 学习目标 什么是多头注意力机制 多头注意力计算机制的作用 多头注意力机…...

【C++】switch 语句编译报错:error: jump to case label

/home/share/mcrockit_3588/prj_linux/../source/rkvpss.cpp: In member function ‘virtual u32 CRkVpss::Control(u32, void*, u32)’: /home/share/mcrockit_3588/prj_linux/../source/rkvpss.cpp:242:8: error: jump to case label242 | case emRkComCmd_DBG_SaveInput:|…...

linux中使用firewall命令操作端口

一、开放端口 1. 开放一个端口 sudo firewall-cmd --zonepublic --add-port8443/tcp --permanent sudo firewall-cmd --reload 2. 开放一组连续端口 sudo firewall-cmd --zonepublic --add-port100-500/tcp --permanent sudo firewall-cmd --reload 3. 一次开放多个不连续…...

C++第六节:stack和queue

本节目标&#xff1a; stack的介绍与使用queue的介绍与使用priority_queue的介绍与使用容器适配器模拟实现与结语 1 stack&#xff08;堆&#xff09;的介绍 stack是一种容器适配器&#xff0c;专门用在具有后进先出操作的上下文环境中&#xff0c;只能从容器的一端进行元素的插…...

算法 并查集

目录 前言 一 并查集的思路 二 并查集的代码分析 三 实操我们的代码 四 并查集的代码优化 总结 前言 并查集主要是用来求解集合问题的&#xff0c;用来查找集合还有就是合并集合&#xff0c;可以把这个运用到最小生成树里面 一 并查集的思路 1 并查集的相关的操作…...

yarn application命令中各参数的详细解释

yarn application 命令用于管理和监控 YARN 上运行的应用程序&#xff0c;下面为你详细解释该命令中各参数的含义和用途&#xff1a; 通用参数 -help [command] 作用&#xff1a;显示 yarn application 命令的帮助信息。如果指定了 command&#xff0c;则显示该子命令的详细使…...

算法之数据结构

目录 数据结构 数据结构与算法面试题 数据结构 《倚天村 • 图解数据结构》 | 小傅哥 bugstack 虫洞栈 ♥数据结构基础知识体系详解♥ | Java 全栈知识体系 线性数据结构 | JavaGuide 数据结构与算法面试题 数据结构与算法面试题 | 小林coding...

Android 图片压缩详解

在 Android 开发中,图片压缩是一个重要的优化手段,旨在提升用户体验、减少网络传输量以及降低存储空间占用。以下是几种主流的图片压缩方法,结合原理、使用场景和优缺点进行详细解析。 效果演示 直接先给大家对比几种图片压缩的效果 质量压缩 质量压缩:根据传递进去的质…...

迷你世界脚本计时器接口:MiniTimer

计时器接口&#xff1a;MiniTimer 彼得兔 更新时间: 2023-04-26 20:24:50 具体函数名及描述如下: 序号 函数名 函数描述 1 isExist(...) 判断计时器是否存在 2 createTimer(...) 添加计时器 3 deleteTimer(...) 删除计时器 4 startBackwardTimer(.…...

JavaScript的变量以及数据类型

JS变量 变量的声明 四种声明方式 1. <script>var abc;abc"变量声明1";alert(abc);</script>2. <script>var abc"变量声明2";alert(abc);</script><script>var abc1,abc2;abc1"变量声明3.1";abc2"变量声明3…...

私有云基础架构

基础配置 使用 VMWare Workstation 创建三台 2 CPU、8G内存、100 GB硬盘 的虚拟机 主机 IP 安装服务 web01 192.168.184.110 Apache、PHP database 192.168.184.111 MariaDB web02 192.168.184.112 Apache、PHP 由于 openEuler 22.09 系统已经停止维护了&#xff…...

在 Windows 和 Linux 系统上安装和部署 Ollama

引言 Ollama 是一个强大的本地大语言模型&#xff08;LLM&#xff09;运行工具&#xff0c;允许用户轻松下载和运行不同的 AI 模型&#xff0c;如 LLaMA、Mistral 和 Gemma。无论是开发者还是研究人员&#xff0c;Ollama 都提供了一种简单而高效的方式来在本地环境中部署 AI 模…...

从零开始学习Slam--数学概念

正交矩阵 矩阵的转置等于它的逆矩阵&#xff0c;这样的矩阵称之为正交矩阵 即&#xff1a; Q T Q I Q^T Q I QTQI&#xff0c; 这样的矩阵列向量都是单位向量且两两正交。 旋转矩阵属于特殊的正交群&#xff0c;即SO(n)&#xff0c;这里n通常是3&#xff0c;所以SO(3)就是…...

微信小程序之bind和catch

这两个呢&#xff0c;都是绑定事件用的&#xff0c;具体使用有些小区别。 官方文档&#xff1a; 事件冒泡处理不同 bind&#xff1a;绑定的事件会向上冒泡&#xff0c;即触发当前组件的事件后&#xff0c;还会继续触发父组件的相同事件。例如&#xff0c;有一个子视图绑定了b…...

ES6从入门到精通:前言

ES6简介 ES6&#xff08;ECMAScript 2015&#xff09;是JavaScript语言的重大更新&#xff0c;引入了许多新特性&#xff0c;包括语法糖、新数据类型、模块化支持等&#xff0c;显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var&#xf…...

盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来

一、破局&#xff1a;PCB行业的时代之问 在数字经济蓬勃发展的浪潮中&#xff0c;PCB&#xff08;印制电路板&#xff09;作为 “电子产品之母”&#xff0c;其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透&#xff0c;PCB行业面临着前所未有的挑战与机遇。产品迭代…...

相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解

【关注我&#xff0c;后续持续新增专题博文&#xff0c;谢谢&#xff01;&#xff01;&#xff01;】 上一篇我们讲了&#xff1a; 这一篇我们开始讲&#xff1a; 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下&#xff1a; 一、场景操作步骤 操作步…...

多场景 OkHttpClient 管理器 - Android 网络通信解决方案

下面是一个完整的 Android 实现&#xff0c;展示如何创建和管理多个 OkHttpClient 实例&#xff0c;分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...

java 实现excel文件转pdf | 无水印 | 无限制

文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...

Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)

概述 在 Swift 开发语言中&#xff0c;各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过&#xff0c;在涉及到多个子类派生于基类进行多态模拟的场景下&#xff0c;…...

Java - Mysql数据类型对应

Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...

NLP学习路线图(二十三):长短期记忆网络(LSTM)

在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...

关于 WASM:1. WASM 基础原理

一、WASM 简介 1.1 WebAssembly 是什么&#xff1f; WebAssembly&#xff08;WASM&#xff09; 是一种能在现代浏览器中高效运行的二进制指令格式&#xff0c;它不是传统的编程语言&#xff0c;而是一种 低级字节码格式&#xff0c;可由高级语言&#xff08;如 C、C、Rust&am…...