2023年3月29日に開催した、「実践的!FPGA開発セミナーvol.20」の当日資料です。
Copyright© Fixstars Group実践的!FPGA開発セミナーvol.202023/03/29 18:00~
View Slide
Copyright© Fixstars GroupEasyNet を使った Vitis による100 Gbps TCP Offloading
Copyright© Fixstars GroupWho I am写真YukiMATSUDA松田 裕貴ソリューション第四事業部 リードエンジニア
Copyright© Fixstars Group自己紹介● 松田裕貴○ 2016 年 4 月に Fixstars に入社○ ハードウェア開発をメインに、ソフトウェア開発なども担当■ FPGA による画像処理・ネットワーク処理■ CPU / GPU 上の処理の高速化○ RTL は極力書きたくない勢
Copyright© Fixstars Group本日のセミナーについて● これまでのセミナーでは、Vitis を使った UDP アプリケーションの作り方等を紹介してきました○ 第2回: Vitis で FPGA ネットワーク通信を手軽に試すテクニック○ 第10回: Vitis-AI 2.0 + Alveo で自前のカーネル + DPU で動かしてみた● 今回のセミナーでは TCP を使ったアプリを作ってみます○ TCP Offload Engine を Vitis から使うためのプロジェクトであるEasyNet を用いて、FPGA 上に TCP Server を実装してみる○ EasyNet と Vitis Libraries の gzip を組み合わせて、gzip server を構築してみる
Copyright© Fixstars Group目次● Introduction● EasyNet を使ってみる● EasyNet と Vitis Libraries の gzip を繋いでみる● まとめ
Copyright© Fixstars GroupTCP Offload Engine (TOE) とは● TCP のパケット処理機能をハードウェア上にオフロードしたもの● TOE に (最低限) 必要な機能○ コネクション確立■ Server の場合 Port Listen, Client の場合 Connect など○ パケットの順序制御・到達保護■ sequence 番号の付与・ack 送信■ checksum validation○ アプリケーションとの通信■ connect, listen, close といったコネクション管理 API の提供■ send, recv といったデータ通信 API の提供
Copyright© Fixstars GroupXilinx FPGA 向けの TOE● Xilinx FPGA 向けだと、以下のようなものが存在する○ パートナー提供■ https://japan.xilinx.com/products/intellectual-property.html からtoe で検索すると色々出てくる○ オープンソース (HLS製、どちらも中身はほぼ同じ)■ https://github.com/fpgasystems/fpga-network-stack● BSD 3-Clause License■ https://github.com/hpcn-uam/100G-fpga-network-stack-core/● BSD 3-Clause License● Xilinx 公式の Vitis Network Example でも使用されている
Copyright© Fixstars Groupfpga-network-stack● https://github.com/fpgasystems/fpga-network-stack● TOE 以外にも、TCP/IP 通信を実現するための機能が含まれている○ Ethernet Header の parse/deparse○ ARP による mac address の解決 (ARP Server)○ ping による疎通確認 (ICMP Server)○ UOE (UDP Offload Engine)● 色々 IP が提供されているが、これを FPGA 上で動かすにはEthernet MAC, network stack, user function 等を繋ぐ必要がある○ これが非常に面倒...
Copyright© Fixstars GroupEasyNet● FPL 2021 で提案された FPGA + TOE の評価環境○ https://ieeexplore.ieee.org/document/9556439○ source: https://github.com/fpgasystems/Vitis_with_100Gbps_TCP-IP● オープンソースの network stack をVitis 経由で簡単に利用できるようにしたもの● 他にも MPI-like communication primitive とかも追加 (今回は未使用)
Copyright© Fixstars GroupVitis になるとどうして開発が楽になるのか?● 通常の FPGA 開発だと、ユーザは design top から全てを作る○ ピン配置、top module, etc.● Vitis による開発だとユーザはユーザロジックのみを作成すればよい (左図)○ I/O 部分等はシェルとして事前に作成されている (ただしボードは固定)● EasyNet の場合、シェルがネットワーク部分まで拡張したような形 (右図)○ TCP を使うアプリケーションだけ FPGA に実装すればよいFPGAShellxdmaDDRDynamicRegionUserLogicFPGAShellxdmaDDRDynamicRegionUserLogicEther macNW stackEasyNet の提供するシェル
Copyright© Fixstars Group参考: FPGA 開発における内部接続の比較 (主観)RTL IP Integrator Vitis簡単さ × 〇 〇柔軟性 〇 △ ×実装の範囲 回路全体 回路全体 ユーザロジックのみ内部の動作 - RTL code を出力 IP Integrator の接続を出力RTL● System Verilog 等でIP の接続を書く● 記述量が多い● generate 文とかは便利● design top から作るIP Integrator (右上図)● GUI で IP を繋ぐので簡単● Intel の場合Platform Designer相当● N 個回路を並べるとかが少し辛い● design top から作るVitis● テキストで論理的な IP の接続を書く● Intel の場合、OneAPI, OpenCL など相当● ユーザロジックだけ作ればシェルと自動で繋がれる
Copyright© Fixstars GroupEasyNet を動かしてみる● EasyNet にはデフォルトでいくつかのユーザーカーネルが用意されている○ iperf2 client/server○ send kernel○ recv kernel○ gather kernel○ all reduce kernel● とりあえず iperf2 server を試してみるhttps://github.com/fpgasystems/Vitis_with_100Gbps_TCP-IP
Copyright© Fixstars Groupチュートリアルデザイン (iperf) を動かしてみる● README 記載の通りにビルドをすると下図のようなデザインができる接続定義ファイル
Copyright© Fixstars Groupチュートリアルデザイン (iperf) を動かしてみる (cont.)● ビットストリーム書き込み後、下図の Host 1 から iperf2 を実行する○ 1回目で合成失敗などもなく、普通に動いた○ i7-9700 環境で MTU=9000 時に 89.2 Gbps => 十分な性能■ MTU=1500 時は 21.5 Gbps● Xeon Gold 6234 でスレッド数が多ければ 100 Gbps 近く出るらしいHost 1NICHost 2Alveo U250100G cable
Copyright© Fixstars GroupEasyNet のインターフェース● EasyNet の IF は左図。よく分からないので C コード (右図) で解説https://github.com/fpgasystems/Vitis_with_100Gbps_TCP-IP
Copyright© Fixstars GroupListen 処理https://github.com/fpgasystems/Vitis_with_100Gbps_TCP-IP①②TOE から port 指定の Listen 要求 => Resp (ok, ng) が返る
Copyright© Fixstars GroupAccept 処理https://github.com/fpgasystems/Vitis_with_100Gbps_TCP-IPAccept (Client の接続通知) に該当する操作はなし。内部的にSession ID が作られる
Copyright© Fixstars GroupRecv 処理https://github.com/fpgasystems/Vitis_with_100Gbps_TCP-IPパケットがTOE に到着後、Notification が来る -> Read Request を送る -> Data が来る1 パケット単位 (1500 Byte くらい) で届くのが CPU との違い①②③
Copyright© Fixstars GroupSend 処理https://github.com/fpgasystems/Vitis_with_100Gbps_TCP-IPデータの送信リクエストを送る -> ok か ng かのレスポンスが返る -> データを送る①②③
Copyright© Fixstars GroupSend 処理https://github.com/fpgasystems/Vitis_with_100Gbps_TCP-IPデータの送信リクエストを送る -> ok か ng かのレスポンスが返る -> データを送る①②③意味さえ分かれば割と簡単なインターフェース
Copyright© Fixstars GroupGZip との接続● Vitis Libraries の xilGzipComp を使用して gzip 圧縮を行う● 通常の AXIS Input と TUSER 付きの AXIS Output を持つ IPhttps://xilinx.github.io/Vitis_Libraries/data_compression/2022.1/source/L2/api_reference.html#xilgzipcomp
Copyright© Fixstars GroupxilGzipComp の使い方● input: 圧縮したいデータを普通に AXIS で入れる○ 末尾にtlast, 末尾以外のtkeep = ALL-1● output:○ 圧縮後のデータが普通に AXIS で出てくる○ AXIS の末尾のワードに圧縮後の length が出てくるinputoutput
Copyright© Fixstars Group余談: xilGzipComp 単体の性能● xilGzipComp だけのプロジェクトを作って性能を計ってみた○ データセット: http://www.mattmahoney.net/dc/textdata.html よりダウンロードできるwikipedia のダンプ■ 100MB, 1GB○ 比較対象: i5-4460 CPU,gzip command (デフォルトオプション)● 特に上限サイズもなさそうで、性能も十分速い圧縮サイズ 圧縮時間CPU 35 MB 4.605 secFPGA 41 MB 0.765 sec圧縮サイズ 圧縮時間CPU 309 MB 40.200 secFPGA 365 MB 5.140 sec100 MB 1 GB
Copyright© Fixstars GroupEasyNet と gzip の接続● 下図のような形で簡単に接続できた (括弧内はコード行数)○ Reader (186): Listen 開始、データ受信○ App Packetize (50): TCP 単位の TLAST をペイロード全体の TLAST に書き換える■ 最初のパケットの先頭に全体の長さを入れて判別○ xilGzipComp: Vitis Libraries そのまま○ Tcp Packetize (124): 圧縮後パケットを MTU 単位で分割する○ Sender (99): データ送信User LogicEasyNet ReaderAppPacketizexilGzipCompTcpPacketizeEasyNetSender
Copyright© Fixstars Group動かしてみた● 圧縮後サイズが 1 パケット長未満のデータまでは動いた○ Tcp Packetize のロジックが固まっていて、より長いデータは動かず...● 反省点○ Vitis を使っているため実装は簡単だったが、合成に 8時間かかってしまったため間に合わず○ やっぱり FPGA で大変なのは合成時間...
Copyright© Fixstars GroupTips: Vitis (Alveo) での ILA の使い方● Vitis だとコンパイルオプションで ila を簡単に追加可能○ --dk chipscope:app_packetize_1:M_AXIS● 普通に Vivado で FPGA に繋ぐだけだと ila が見えなかったのでやり方を記載○ 基本的にはhttps://docs.xilinx.com/r/en-US/ug1393-vitis-application-acceleration/Automated-Setup-for-Hardware-Debug の内容を実施すればよい
Copyright© Fixstars GroupTips: Vitis (Alveo) での ILA の使い方 (cont.)● Alveo を搭載したマシンで次のコマンドを実行して hw_server を立ち上げる○ debug_hw --xvc_pcie /dev/xfpga/xvc_pub.XX --hw_server● 合成したマシンで次のコマンドで ltx を指定して vivado を立ち上げ○ debug_hw --vivado --host --ltx_file./_x/link/vivado/vpl/prj/prj.runs/impl_1/debug_nets.ltx● こうすると、HW Manager の画面が自動的に立ち上がり、ila でのデバッグが可能
Copyright© Fixstars Groupまとめ● EasyNet を使って TOE のシェルと gzip 回路を結合してみた● 結果○ 合成時間が想定外に長かったため、全体は動かず...● 所感○ お手軽に TOE を FPGA で触れるのはすごく良い■ Vitis を使っているので実装はかなり簡単■ Vivado の GUI を使わなくて良いのが気軽で良い■ このように色々な I/O を Vitis で触れるようになると楽でいいなーという感じ○ 結局合成時間が開発時間以上にかかるので、大きなものを作るとこっちがボトルネック■ TOE までシェルに入れてユーザーロジックのみ DFX で合成できれば良いのかも
Copyright© Fixstars Group予備スライド● xilGzipComp のリソース使用量
Copyright© Fixstars GroupLightning Talk!
Copyright© Fixstars Groupopen-nicの高速化
Copyright© Fixstars GroupWho I amTakashiUCHIDA内田 崇ソリューション第四事業部 エンジニア
Copyright© Fixstars Groupopen-nicとは?● AMD Xilinxから出ているFPGA designおよびdriver(https://github.com/Xilinx/open-nic)● open source (Apache License 2.0)● 内部ロジックをカスタムで追加可能 (今回は未実施)
Copyright© Fixstars Groupopen-nic の FPGA design 概要● HOST - FPGA 間の通信は PCIe 経由でQDMA で行われる● QSFP の制御は CMAC IP が使用されている● ユーザーロジックを追加できる領域は 2箇所 (左図の灰色部)● CMAC のポート数や QDMA の physicalfunction の実装数などをパラメータ設定可能FPGA design 全体図(githubのREADMEから抜粋)引用元:https://github.com/Xilinx/open-nic-shell
Copyright© Fixstars Group性能確認環境HOST 1(Ubuntu 20.04.4 LTS)HOST 2(Ubuntu 22.04.1 LTS)Alveo U250(192.168.10.1)ConnectX-5(192.168.10.2)100Gbps DACケーブル● iperf で throughput を測定した● 並列数を 8 で実行 (確保される queue が 8 本だったため)● open-nic 側を server / client の各々で実行● 今回は「高速化 = throughput を上げる」の意味で使用
Copyright© Fixstars Groupopen-nic の性能確認確認open-nic (@client) open-nic (@server)throughput [Gbps] 21.6 4.12● open-nic を iperf の server として実行した場合の性能が低い● Receive 側の方が負荷が大きく、性能が下がりやすいのは一般的● Mellanox NIC(ConnectX-5) でも RSS (Recieve Side Scaling) などの対策が取られている
Copyright© Fixstars Groupiperf 実行時の CPU 使用率● open-nic を動作させているHOST の CPU (i5) の性能があまり高くなく resource を使いきっている● open-nic 側の Host の性能を上げて確認したほうが良いが、今回はこのまま確認を継続したopen-nic 側ConnectX-5 側
Copyright© Fixstars Groupopen-nic の RSS の動作確認● open-nic は RSS (Recieve Side Scaling) を サポートしている● 仕組みは以下の通り1. driver install 時に driver から FPGA の register に qid を順に書き込む2. FPGA 側で Toeplitz で hash 値を計算し、結果を address として register から qid を読み出す/* inform shell about the function map */val = (FIELD_SET(QDMA_FUNC_QCONF_QBASE_MASK, qbase) |FIELD_SET(QDMA_FUNC_QCONF_NUMQ_MASK, qmax));onic_write_reg(hw, QDMA_FUNC_OFFSET_QCONF(func_id), val);/* initialize indirection table */for (i = 0; i < 128; ++i) {u32 val = (i % qmax) & 0x0000FFFF;u32 offset = QDMA_FUNC_OFFSET_INDIR_TABLE(func_id, i);onic_write_reg(hw, offset, val);}open-nic-driver code 抜粋
Copyright© Fixstars Groupopen-nic の RSS の動作確認結果● 対向の Mellanox NIC から open-nic に 1000 回 ping を投げた結果を以下に示す● 各 queue に概ね均等に割り振られている● 割り付けられている core が偏っているのは driver で特にコントロールしていないからだと思われる○ 今回実験している HOST が 4 core なのでその影響の可能性は十分考えられる$ cat /proc/interruptsCPU0 CPU1 CPU2 CPU334: 128 0 0 0 PCI-MSI 524288-edge onic1s0f0-035: 114 0 0 0 PCI-MSI 524289-edge onic1s0f0-136: 0 136 0 0 PCI-MSI 524290-edge onic1s0f0-237: 0 0 0 142 PCI-MSI 524291-edge onic1s0f0-338: 117 0 0 0 PCI-MSI 524292-edge onic1s0f0-439: 0 124 0 0 PCI-MSI 524293-edge onic1s0f0-540: 0 0 127 0 PCI-MSI 524294-edge onic1s0f0-641: 0 0 0 143 PCI-MSI 524295-edge onic1s0f0-742: 0 0 0 0 PCI-MSI 524296-edge onic-user43: 0 0 0 0 PCI-MSI 524297-edge onic-errorデータ用MSI-X 用
Copyright© Fixstars GroupFPGA のボトルネックを確認する (open-nic @client)● cmac への入力で ready が落とされている● 入力の valid の頻度からするとあまり影響はないと考えられる
Copyright© Fixstars GroupFPGA のボトルネックを確認する (open-nic @server)● QDMA IP への入力 stream で ready が落ちている● IP の処理があまり早くない可能性も 0 ではないが、HOST の処理が遅いためと思われる
Copyright© Fixstars Groupopen-nic-driver の修正 (MTU 設定値を上げる)● FPGA 側のボトルネックはなさそう● open-nic-driver を変更して throughput の向上を試みる● 始めに MTU を上げる○ default だと open-nic-driver は MTU を設定できるようにはなっていないので、driver のコードを修正する必要がある
Copyright© Fixstars GroupMTU 設定のための修正 1● netdev 構造体の max_mtu の値を 設定する○ default 値は 1500 になっている$ git diff onic_main.cdiff --git a/onic_main.c b/onic_main.cindex b0eb3b1..bb70614 100644--- a/onic_main.c+++ b/onic_main.c@@ -217,6 +217,8 @@ static int onic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)}priv->pdev = pdev;priv->netdev = netdev;+ priv->netdev->max_mtu = 9000;+spin_lock_init(&priv->tx_lock);spin_lock_init(&priv->rx_lock);
Copyright© Fixstars GroupMTU 設定のための修正 2● ip command などで MTU 設定時に呼び出される関数内で引数で MTU 値を更新する○ open-nic の default だと以下のように関数だけ準備されているので追加する$ git diff onic_netdev.cdiff --git a/onic_netdev.c b/onic_netdev.cindex 7449092..0da634d 100644--- a/onic_netdev.c+++ b/onic_netdev.c@@ -764,6 +764,7 @@ int onic_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)int onic_change_mtu(struct net_device *dev, int mtu){netdev_info(dev, "Requested MTU = %d", mtu);+ dev->mtu = mtu;return 0;}
Copyright© Fixstars GroupMTU 設定のための修正 3● FPGAの合成を option を以下のように指定して実行● ここまで実行しても、 MTU は 4K までしか動作しなかった○ 理由は driver 内で受信 queue の initialize 時に (packet size に関係なく) page size (4K) 分確保しているため○ 単純に 確保 size の数値を増やしてみたが効果がなかった○ 上記のため iperf で MSS を 4000 にして性能を比較したvivado -mode batch -source build.tcl -tclargs -board au250 -max_pkt_len 9600
Copyright© Fixstars GroupMSS = 4000 での iperf 測定結果● MSS = 1500 と比較して iperf の性能が両方向ともに向上することが確認できたMSS open-nic (@client) open-nic (@server)1500 21.6 4.124000 30.4 9.29
Copyright© Fixstars Groupopen-nic-driver の改善 (QUEUE の数を増やせるか?)● QUEUE の数は何段階か経て driver 内で最適化されるが、実質的には以下の関数で制限されている● kernel の関数をたどると、最終的には hardware の register を読んで決定しているようで、software 的な変更は簡単ではなさそうだったvectors = pci_alloc_irq_vectors(priv->pdev, non_q_vectors + 1, vectors, PCI_IRQ_MSIX);
Copyright© Fixstars Groupopen-nic-dpdk● open-nic が用意しているもう一つの driver● 一般的に dpdk を使用すると kernel module の driver と比較してoverehead がなくなり、 buffer の sizeも拡大できそう○ MTU の制約もなくなりそうだし、単純に速く動作すると期待できる引用元:https://www.ntt-tx.co.jp/column/dpdk_blog/190610/
Copyright© Fixstars Groupopen-nic-dpdk 結果 (動作まで至らず)● open-nic-dpdk の github の手順通りに進めたが、Section 8 の bind が動作せず● コードを追っていくと、lspci で得た Device が期待と異なっていてエラーになっていた○ lspci で得られた結果は以下の通りだが、コードで期待してるのは実行時に引き渡す引数 (vfio-pci)○ なぜか qdma_pf (Xilinx の qdma driver)が default で load されてしまい、いろいろ試したが解決に至らなかった$ lspci -vmmks 01:00.0Slot: 01:00.0Class: Memory controllerVendor: Xilinx CorporationDevice: Device 903fSVendor: Xilinx CorporationSDevice: Device 0007Module: qdma_pfopen-nic-dpdk:https://github.com/Xilinx/open-nic-dpdk
Copyright© Fixstars Groupまとめ● open-nic-driver を MTU を設定できるように変更したところ多少の性能向上(最大 30.04 Gbps) が得られた● open-nic-dpdk での改善を期待したが、今回は動作まで至らなかった
Copyright © Fixstars GroupThank you!お問い合わせ窓口 : [email protected]