中華智能自建代理網(wǎng)站搜索引擎優(yōu)化推廣
目錄
- Sionna:用于 6G 物理層研究的開源庫
- 主要特點(diǎn)
- 實(shí)現(xiàn)6G研究的民主化
- 支持 5G、6G 等
- 模塊化、可擴(kuò)展、可伸縮
- 快速啟動(dòng)您的研究
- 好處
- 原生人工智能支持
- 綜合研究平臺(tái)
- 開放生態(tài)系統(tǒng)
- 安裝
- 筆記
- 使用 pip 安裝
- 基于Docker的安裝
- 從源代碼安裝
- “你好世界!”
- 探索錫奧納 (Sionna)?
- 加載所需包?
- 首次鏈路級(jí)仿真?
- 建立端到端模型?
- 運(yùn)行一些吞吐量測(cè)試(圖形模式)?
- 誤碼率 (BER) 蒙特卡羅模擬?
- 結(jié)論?
Sionna:用于 6G 物理層研究的開源庫
Sionna ?是一個(gè)用于鏈路級(jí)仿真的 GPU 加速開源庫。它能夠快速構(gòu)建復(fù)雜通信系統(tǒng)架構(gòu)的原型,并為機(jī)器學(xué)習(xí)在 6G 信號(hào)處理中的集成提供原生支持。
Sionna ? 是一個(gè)基于TensorFlow的開源庫,用于模擬無線和光通信系統(tǒng)的物理層。復(fù)雜通信系統(tǒng)架構(gòu)的快速原型設(shè)計(jì)就像連接所需的構(gòu)建塊一樣簡(jiǎn)單,這些構(gòu)建塊以Keras層的形式提供。使用可微分層,梯度可以在整個(gè)系統(tǒng)中反向傳播,這是系統(tǒng)優(yōu)化和機(jī)器學(xué)習(xí),尤其是神經(jīng)網(wǎng)絡(luò)集成的關(guān)鍵推動(dòng)因素。NVIDIA GPU 加速提供了數(shù)量級(jí)更快的模擬,從而實(shí)現(xiàn)了對(duì)此類系統(tǒng)的交互式探索,例如,在可以在Google Colab等云服務(wù)上運(yùn)行的Jupyter 筆記本中。如果沒有可用的 GPU,Sionna 將在 CPU 上運(yùn)行。
Sionna 由 NVIDIA 開發(fā)、不斷擴(kuò)展和使用,以推動(dòng) 5G 和 6G 研究。它支持 MU-MIMO(多用戶多輸入多輸出)鏈路級(jí)模擬設(shè)置,具有符合 5G 的代碼,包括低密度奇偶校驗(yàn) (LDPC) 和 Polar 編碼/解碼器、3GPP 信道模型、OFDM(正交頻分復(fù)用)、信道估計(jì)、均衡和軟解映射。還有許多其他組件可用,例如卷積碼和 Turbo 碼、用于模擬光纖信道的分步傅里葉方法以及用于研究單載波波形的濾波器和窗口。每個(gè)構(gòu)建塊都是一個(gè)獨(dú)立的模塊,可以根據(jù)您的需求輕松測(cè)試、理解和修改。
主要特點(diǎn)
實(shí)現(xiàn)6G研究的民主化
Sionna 實(shí)現(xiàn)了一系列經(jīng)過精心測(cè)試的先進(jìn)算法,可用于基準(zhǔn)測(cè)試和端到端性能評(píng)估。這讓您可以專注于研究,使其更具影響力和可重復(fù)性,同時(shí)減少花在實(shí)現(xiàn)專業(yè)領(lǐng)域之外的組件上的時(shí)間。Sionna 是下一代通信系統(tǒng)(如 6G)物理層研究的寶貴工具。
支持 5G、6G 等
Sionna 由 NVIDIA 開發(fā)、不斷擴(kuò)展和使用,用于推動(dòng) 5G 和 6G 物理層研究。它支持越來越多的功能,例如使用符合 5G 標(biāo)準(zhǔn)的低密度奇偶校驗(yàn) (LDPC) 和 Polar 碼進(jìn)行多用戶多輸入多輸出 (MU-MIMO) 鏈路級(jí)模擬、3GPP TR38.901 信道模型和射線追蹤、正交頻分復(fù)用 (OFDM)、信道估計(jì)等。
模塊化、可擴(kuò)展、可伸縮
每個(gè)構(gòu)建塊都是一個(gè)獨(dú)立的模塊,您可以根據(jù)需要輕松測(cè)試、理解和修改。Sionna 提供高級(jí) Python 應(yīng)用程序編程接口 (API),可輕松建模復(fù)雜的通信系統(tǒng),同時(shí)提供充分的靈活性以適應(yīng)您的研究?;?TensorFlow,Sionna 可自動(dòng)跨多個(gè) GPU 擴(kuò)展。
快速啟動(dòng)您的研究
Sionna 附帶大量文檔,包括許多可幫助您盡快入門的教程。Sionna 開箱即用,支持 NVIDIA GPU,速度極快,非常適合通信領(lǐng)域的機(jī)器學(xué)習(xí)研究。
好處
原生人工智能支持
Sionna 是第一個(gè)完全可微分的鏈接級(jí)模擬器,它使神經(jīng)網(wǎng)絡(luò)的集成變得輕而易舉。
綜合研究平臺(tái)
綜合研究平臺(tái)
Sionna 將鏈路級(jí)和通道模擬功能與原生機(jī)器學(xué)習(xí)和 GPU 支持相結(jié)合。
開放生態(tài)系統(tǒng)
Sionna 是基于 Python 的開源項(xiàng)目,歡迎第三方的貢獻(xiàn)。
安裝
Sionna 需要Python和Tensorflow。為了在您的機(jī)器上運(yùn)行教程筆記本,您還需要JupyterLab 。您也可以在Google Colab上測(cè)試它們。雖然不是必需的,但我們建議在Docker 容器中運(yùn)行 Sionna 。
筆記
Sionna 需要TensorFlow 2.13-2.15和 Python 3.8-3.11。我們推薦使用 Ubuntu 22.04。早期版本的 TensorFlow 可能仍能使用,但由于已知未修補(bǔ)的 CVE,因此不推薦使用。
要在 CPU 上運(yùn)行光線追蹤器,DrJit 需要LLVM 。請(qǐng)查看LLVM 后端的安裝說明。光線追蹤預(yù)覽需要最新版本的JupyterLab 。您可以通過(需要重新啟動(dòng)JupyterLab)升級(jí)到最新版本。pip install --upgrade ipykernel jupyterlab
我們參考TensorFlow GPU 支持教程來了解 GPU 支持和所需的驅(qū)動(dòng)程序設(shè)置。
使用 pip 安裝
我們建議在虛擬環(huán)境中執(zhí)行此操作,例如使用conda。在 macOS 上,您需要先安裝tensorflow-macos。
1.)安裝軟件包
pip install sionna
2.)在 Python 中測(cè)試安裝
python>>> import sionna
>>> print(sionna.__version__)
0.19.2
3.) 一旦安裝了 Sionna,您就可以運(yùn)行Sionna“Hello, World!”示例,查看快速入門指南或教程。
對(duì)于本地安裝,可以使用JupyterLab Desktop應(yīng)用程序。這直接包括 Python 的安裝和配置。
基于Docker的安裝
1.) 確保你的系統(tǒng)上安裝了Docker 。在 Ubuntu 22.04 上,你可以運(yùn)行例如
sudo apt install docker.io
確保您的用戶屬于docker組(請(qǐng)參閱Docker 安裝后)。
sudo usermod -aG docker $USER
注銷并重新登錄以加載更新的群組成員資格。
為了在 Linux 上獲得 GPU 支持,您需要安裝NVIDIA Container Toolkit。
2.) 構(gòu)建 Sionna Docker 映像。在 Sionna 目錄中,運(yùn)行:
make docker
3.) 運(yùn)行支持 GPU 的 Docker 鏡像
make run-docker gpus=all
或者不使用 GPU:
make run-docker
這將立即啟動(dòng)安裝了 Sionna 的 Docker 映像,并在端口 8888 上運(yùn)行 JupyterLab。
4.) 通過在瀏覽器中連接http://127.0.0.1:8888瀏覽示例筆記本。
從源代碼安裝
我們建議在虛擬環(huán)境中執(zhí)行此操作,例如使用conda。
1.) 克隆此存儲(chǔ)庫并從其根文件夾中執(zhí)行:
make install
2.)在 Python 中測(cè)試安裝
python
>>> import sionna
>>> print(sionna.__version__)
0.19.2
“你好世界!”
導(dǎo)入 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
讓我們首先創(chuàng)建一個(gè)BinarySource來生成一批隨機(jī)的位向量,我們可以將其映射到星座符號(hào):
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=
數(shù)組([[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)>
接下來,讓我們創(chuàng)建一個(gè)星座并將其可視化:
constellation = sionna.mapping.Constellation("qam", num_bits_per_symbol)
constellation.show();
我們現(xiàn)在需要一個(gè)映射器,根據(jù)上面顯示的位標(biāo)記將 b 的每一行映射到星座符號(hào)。
mapper = sionna.mapping.Mapper(constellation=constellation)
x = mapper(b)
x[:10]
<tf.Tensor:形狀=(10,1),dtype=complex64,numpy=
數(shù)組([[ 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)>
現(xiàn)在讓我們讓事情變得更有趣一點(diǎn),通過AWGN 信道發(fā)送我們的符號(hào):
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)?
本示例筆記本將引導(dǎo)您了解基本原理并說明Sionna的主要功能。只需幾個(gè)命令,您就可以模擬許多符合 5G 標(biāo)準(zhǔn)的組件的 PHY 層鏈路級(jí)性能,包括輕松可視化結(jié)果。
加載所需包?
必須安裝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 中運(yùn)行 bash 命令!。
!nvidia-smi
2024 年 9 月 26 日星期四 14:40:00
+------------------------------------------------------------------------------------------------+
| NVIDIA-SMI 535.183.01 驅(qū)動(dòng)程序版本:535.183.01 CUDA 版本:12.2 |
|----------------------------------------+----------------------+--------------------------------+
| GPU 名稱 Persistence-M | Bus-Id Disp.A | 易失性 Uncorr. ECC |
| 風(fēng)扇溫度性能功率:使用情況/容量 | 內(nèi)存使用情況 | GPU-Util 計(jì)算 M。|
| | | 米格 M. |
|=========================================+========================+======================|
| 0 NVIDIA GeForce RTX 3090 關(guān)閉 | 00000000:01:00.0 關(guān)閉 | N/A |
| 0% 48C P2 39W / 350W | 292MiB / 24576MiB | 0% 默認(rèn) |
| | | 不適用|
+----------------------------------------------------+----------------------+--------------------------------+
| 1 NVIDIA GeForce RTX 3090 關(guān)閉 | 00000000:4D:00.0 關(guān)閉 | N/A |
| 30% 42C P8 23W / 350W | 3MiB / 24576MiB | 0% 默認(rèn) |
| | | 不適用|
+----------------------------------------------------+----------------------+--------------------------------++------------------------------------------------------------------------------------------------+
| 流程: |
| GPU GI CI PID 類型 進(jìn)程名稱 GPU 內(nèi)存 |
| ID ID使用情況 |
|=============================================================================================|
+------------------------------------------------------------------------------------------------+
如果有多個(gè) GPU 可用,我們會(huì)將此筆記本限制為單 GPU 使用。如果只有一個(gè) GPU 可用,則可以忽略此命令。
此外,我們希望避免此筆記本在初始化并設(shè)置memory_growth為活動(dòng)狀態(tài)時(shí)實(shí)例化整個(gè) GPU 內(nèi)存。
備注:Sionna 不需要 GPU。所有內(nèi)容也可以在 CPU 上運(yùn)行 - 但您可能需要等待一段時(shí)間。
# 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 數(shù)據(jù)流和設(shè)計(jì)范式?
Sionna 本質(zhì)上通過批處理實(shí)現(xiàn)模擬并行化,即批處理維度中的每個(gè)元素都是獨(dú)立模擬的。
這意味著第一個(gè)張量維度始終用于幀間并行化,類似于Matlab/NumPy 模擬中的外部for 循環(huán)。
為了保持?jǐn)?shù)據(jù)流高效,Sionna 遵循一些簡(jiǎn)單的設(shè)計(jì)原則:
信號(hào)處理組件作為單獨(dú)的Keras 層實(shí)現(xiàn)。
tf.float32分別用作首選數(shù)據(jù)類型和tf.complex64復(fù)值數(shù)據(jù)類型。這允許更簡(jiǎn)單地重復(fù)使用組件(例如,相同的置亂層可用于二進(jìn)制輸入和 LLR 值)。
模型可以在急切模式下開發(fā),從而允許簡(jiǎn)單(且快速)地修改系統(tǒng)參數(shù)。
可以在更快的圖形模式下執(zhí)行數(shù)字運(yùn)算模擬,甚至可以為大多數(shù)組件提供XLA加速。
只要有可能,組件就會(huì)通過自動(dòng)分級(jí)自動(dòng)區(qū)分,以簡(jiǎn)化深度學(xué)習(xí)設(shè)計(jì)流程。
代碼被構(gòu)建為用于不同任務(wù)的子包,例如通道編碼、映射等(有關(guān)詳細(xì)信息,請(qǐng)參閱API 文檔)。
劃分為單獨(dú)的塊簡(jiǎn)化了部署,并且所有層和功能都附帶單元測(cè)試以確保其正確的行為。
這些范例簡(jiǎn)化了我們的組件在廣泛的通信相關(guān)應(yīng)用程序中的可重用性和可靠性。
關(guān)于隨機(jī)數(shù)生成的注釋?
加載 Sionna 時(shí),它會(huì)實(shí)例化Python、NumPy和TensorFlow的隨機(jī)數(shù)生成器 (RNG) 。您可以選擇設(shè)置一個(gè)種子,只要只使用這些 RNG,它就會(huì)使所有結(jié)果都具有確定性。在下面的單元格中,您可以看到如何設(shè)置此種子以及如何使用不同的 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 文檔查找所有現(xiàn)有組件的概述。
我們現(xiàn)在想通過 AWGN 信道傳輸一些符號(hào)。首先,我們需要初始化相應(yīng)的層。
channel = sionna.channel.AWGN() # init AWGN channel layer
在第一個(gè)例子中,我們想要將高斯噪聲添加到某些給定值中x。
記住 - 第一個(gè)維度是批次維度。
我們模擬 2 個(gè)消息幀,每個(gè)幀包含 4 個(gè)符號(hào)。
備注:AWGN信道定義為復(fù)值。
# 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 的信道。為此,我們可以簡(jiǎn)單地調(diào)用之前定義的層channel。
如果您從未使用過Keras,那么您可以將層視為一個(gè)函數(shù):它有一個(gè)輸入并返回處理后的輸出。
備注:每次執(zhí)行此單元時(shí)都會(huì)繪制一個(gè)新的噪聲實(shí)現(xiàn)。
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)
噪聲符號(hào)為: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 原生支持多維張量。
大多數(shù)層在最后一個(gè)維度上運(yùn)行,并且可以具有任意輸入形狀(在輸出時(shí)保留)。
假設(shè)我們想為長度為 500 的 64 個(gè)代碼字添加 CRC-24 校驗(yàn)(例如,每個(gè)子載波不同的 CRC)。此外,我們想在一批 100 個(gè)樣本上并行化模擬。
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)
已處理位數(shù):3353600
u_hat 的形狀:(100、64、500)
crc_valid 的形狀:(100,64,1)
第一個(gè)代碼字的有效 CRC 校驗(yàn):真
我們想做另一個(gè)模擬,但針對(duì) 5 個(gè)獨(dú)立用戶。
我們不需要定義 5 個(gè)不同的張量,只需添加另一個(gè)維度即可。
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)
已處理位數(shù):16768000
良好的結(jié)果可視化往往有助于獲得新的研究思路。因此,Sionna 具有內(nèi)置的繪圖功能。
讓我們看一下16-QAM星座。
constellation = sionna.mapping.Constellation("qam", num_bits_per_symbol=4)
constellation.show();
首次鏈路級(jí)仿真?
我們已經(jīng)可以用幾個(gè)簡(jiǎn)單的命令來構(gòu)建強(qiáng)大的代碼。
如前所述,Sionna 旨在將系統(tǒng)復(fù)雜性隱藏到 Keras 層中。但是,我們?nèi)匀幌M峁┍M可能多的靈活性。因此,大多數(shù)層都有幾種初始參數(shù)選擇,但通常默認(rèn)選擇是一個(gè)好的開始。
提示:API 文檔提供了許多有用的參考和實(shí)現(xiàn)細(xì)節(jié)。
# 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)
通常,會(huì)實(shí)現(xiàn)幾種不同的算法,例如,解映射器支持“true app”解映射,也支持“max-log”解映射。
LDPC BP譯碼器的校驗(yàn)節(jié)點(diǎn)(CN)更新功能也支持多種算法。
demapping_method = "app" # try "max-log"
ldpc_cn_type = "boxplus" # try also "minsum"
讓我們根據(jù)給定的系統(tǒng)參數(shù)初始化所有必需的組件。
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)
我們現(xiàn)在可以在Eager 模式下運(yùn)行代碼。這允許我們隨時(shí)修改結(jié)構(gòu) - 您可以嘗試不同的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 位
總結(jié)一下:我們模擬了 250,000 比特的傳輸,包括高階調(diào)制和信道編碼!
但是我們可以通過TF 圖形執(zhí)行甚至更快地完成任務(wù)!
建立端到端模型?
我們現(xiàn)在定義一個(gè)更方便訓(xùn)練和蒙特卡洛模擬的Keras 模型。
我們模擬了時(shí)變多徑信道( 3GPP TR38.901 中的TDL-A模型)上的傳輸。為此,我們使用了 OFDM 和具有高階調(diào)制的傳統(tǒng)比特交織編碼調(diào)制 (BICM) 方案。信息比特受 5G 兼容 LDPC 碼保護(hù)。
備注:由于參數(shù)數(shù)量較多,我們將其定義為字典。
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
讓我們將模擬的系統(tǒng)參數(shù)定義為字典:
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)
飛行員人數(shù):512
數(shù)據(jù)符號(hào)數(shù):3072
資源元素?cái)?shù)量:3584
飛行員開銷:14.29%
循環(huán)前綴開銷:5.88%
每幀包含6144個(gè)信息位
與以前一樣,我們可以簡(jiǎn)單地調(diào)用模型來模擬給定模擬參數(shù)的 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 且模擬比特?cái)?shù)為 1228800 時(shí)為 0.001245
運(yùn)行一些吞吐量測(cè)試(圖形模式)?
Sionna 不僅是一個(gè)易于使用的庫,而且速度非???。讓我們測(cè)量一下上面定義的模型的吞吐量。
我們比較了eager和graph執(zhí)行模式(詳情請(qǐng)參閱Tensorflow 文檔),以及XLA 的 eager(請(qǐng)參閱https://www.tensorflow.org/xla#enable_xla_for_tensorflow_models)。請(qǐng)注意,我們需要激活sionna.config.xla_compat功能才能使 XLA 正常工作。
提示:更改batch_size以查看批處理并行性如何提高吞吐量。根據(jù)您的機(jī)器,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 可能導(dǎo)致數(shù)值精度降低。請(qǐng)謹(jǐn)慎使用。
Eager Execution 吞吐量:1.56 Mb/s
圖形執(zhí)行吞吐量:7.76 Mb/s
XLA 圖形執(zhí)行的吞吐量:57.66 Mb/s
顯然,圖形執(zhí)行(使用 XLA)可產(chǎn)生更高的吞吐量(至少如果有快速 GPU 可用)。因此,對(duì)于詳盡訓(xùn)練和蒙特卡羅模擬,圖形模式(使用 XLA 和 GPU 加速)是首選。
誤碼率 (BER) 蒙特卡羅模擬?
蒙特卡羅模擬在當(dāng)今的通信研究和開發(fā)中無處不在。由于其高性能實(shí)現(xiàn),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 可能導(dǎo)致數(shù)值精度降低。請(qǐng)謹(jǐn)慎使用。
EbNo [dB] | BER | BLER | 比特錯(cuò)誤 | 比特?cái)?shù) | 塊錯(cuò)誤 | 塊數(shù) | 運(yùn)行時(shí)間 [s] | 狀態(tài)
-------------------------------------------------------------------------------------------------------------------------------------------0.0 | 3.4352e-01 | 1.0000e+00 | 1266347 | 3686400 | 600 | 600 | 0.1 |達(dá)到目標(biāo)塊錯(cuò)誤1.0 | 3.2095e-01 | 1.0000e+00 | 1183166 | 3686400 | 600 | 600 | 0.1 |達(dá)到目標(biāo)塊錯(cuò)誤2.0 | 2.9738e-01 | 1.0000e+00 | 1096268 | 3686400 | 600 | 600 | 0.1 |達(dá)到目標(biāo)塊錯(cuò)誤3.0 | 2.7369e-01 | 1.0000e+00 | 1008918 | 3686400 | 600 | 600 | 0.1 |達(dá)到目標(biāo)塊錯(cuò)誤4.0 | 2.4703e-01 | 1.0000e+00 | 910649 | 3686400 | 600 | 600 | 0.1 |達(dá)到目標(biāo)塊錯(cuò)誤5.0 | 2.1839e-01 | 1.0000e+00 | 805067 | 3686400 | 600 | 600 | 0.1 |達(dá)到目標(biāo)塊錯(cuò)誤6.0 | 1.8570e-01 | 1.0000e+00 | 684560 | 3686400 | 600 | 600 | 0.1 |達(dá)到目標(biāo)塊錯(cuò)誤7.0 | 1.1760e-01 | 9.9167e-01 | 433539 | 3686400 | 595 | 600 | 0.1 |達(dá)到目標(biāo)塊錯(cuò)誤8.0 | 4.2571e-02 | 4.7833e-01 | 313870 | 7372800 | 574 | 1200 | 0.2 |達(dá)到目標(biāo)塊錯(cuò)誤9.0 | 1.3462e-02 | 1.5206e-01 | 281220 | 20889600 | 517 | 3400 | 0.4 |達(dá)到目標(biāo)塊錯(cuò)誤10.0 | 3.3929e-03 | 3.5352e-02 | 296011 | 87244800 | 502 | 14200 | 1.8 |達(dá)到目標(biāo)塊錯(cuò)誤11.0 | 8.4720e-04 | 9.1758e-03 | 284203 | 335462400 | 501 | 54600 | 6.8 |達(dá)到目標(biāo)塊錯(cuò)誤12.0 | 2.7327e-04 | 2.9002e-03 | 289455 | 1059225600 | 500 | 172400 | 21.3 |達(dá)到目標(biāo)塊錯(cuò)誤13.0 | 8.8057e-05 | 8.9500e-04 | 108205 | 1228800000 | 179 | 200000 | 24.5 |已達(dá)到最大迭代次數(shù)14.0 | 3.4128e-05 | 3.3500e-04 | 41936 | 1228800000 | 67 | 200000 | 24.5 |已達(dá)到最大迭代次數(shù)
我們來看看結(jié)果。
sionna.utils.plotting.plot_ber(ebno_dbs,ber_mc,legend="E2E Model",ylabel="Coded BER");
結(jié)論?
我們希望您對(duì) Sionna 感到興奮——還有更多的東西有待發(fā)現(xiàn):
TensorBoard 調(diào)試可用
擴(kuò)展到多 GPU 模擬很簡(jiǎn)單
請(qǐng)參閱可用的教程以獲取更多高級(jí)示例。