深入淺出DPDK閱讀筆記

深入淺出DPDK

第一章 概述

第二章 Cache和內存

Cache預取

DPDK會在代碼層面對數據報文做預取

Cache一致性

要解決以下兩個問題:

1、Cache對齊

2、多核訪問的衝突

解決方法:

1、數據定義邊界對齊

2、每個核單獨享有自己的數據結構

3、對於必然同時訪問的臨界區,對於網絡端口而講,網卡有多隊列,每個核用自己的隊列。其他的臨界區——應該不可避免要用一些窺探協議來處理

TLB問題與大頁

如果採用常規頁(4KB) 並且使TLB總能命中, 那麼至少需要在TLB表中存放兩個表項, 在這種情況下, 只要尋址的內容都在該內容頁內, 那麼兩個表項就足夠了。 如果一個程序使用了512個內容頁也就是2MB大小, 那麼需要512個頁表表項才能保證不會出現TLB不命中的情況。 通過上面的介紹, 我們知道TLB大小是很有限的, 隨着程序的變大或者程序使用內存的增加, 那麼勢必會增加TLB的使用項, 最後導致TLB出現不命中的情況。

解決方法:使用大頁

 

DDIO

Data Direct I/O技術。

當一個網絡報文送到服務器的網卡時, 網卡通過外部總線(比如PCI總線) 把數據和報文描述符送到內存。 接着, CPU從內存讀取數據到Cache進而到寄存器。 進行處理之後, 再寫回到Cache, 並最終送到內存中。 最後, 網卡讀取內存數據, 經過外部總線送到網卡內部, 最終通過網絡接口發送出去。可以看出, 對於一個數據報文, CPU和網卡需要多次訪問內存。 而內存相對CPU來講是一個非常慢速的部件。 CPU需要等待數百個週期才能拿到數據, 在這過程中, CPU什麼也做不了。

DDIO技術是如何改進的呢? 這種技術使外部網卡和CPU通過LLC Cache(Last Level Cache)直接交換數據, 繞過了內存這個相對慢速的部件。 這樣, 就增加了CPU處理網絡報文的速度(減少了CPU和網卡等待內存的時間) , 減小了網絡報文在服務器端的處理延遲。 這樣做也帶來了一個問題, 因爲網絡報文直接存儲在LLC Cache中, 這大大增加了對其容量的需求, 因而在英特爾的E5處理器系列產品中, 把LLC Cache的容量提高到了20MB。

NUMA系統

DPDK在NUMA系統中的一些實例:

1) Per-core memory。 一個處理器上有多個核(core) , per-core memory是指每個核都有屬於自己的內存, 即對於經常訪問的數據結構, 每個核都有自己的備份。 這樣做一方面是爲了本地內存的需要, 另外一方面也是因爲上文提到的Cache一致性的需要, 避免多個核訪問同一個Cache行。

2) 本地設備本地處理。 即用本地的處理器、 本地的內存來處理本地的設備上產生的數據。 如果有一個PCI設備在node0上, 就用node0上的核來處理該設備, 處理該設備用到的數據結構和數據緩衝區都從node0上分配。 以下是一個分配本地內存的例子:

/* allocate memory for the queue structure */

q = rte_zmalloc_socket("fm10k", sizeof(*q), RTE_CACHE_LINE_SIZE, socket_id);

該例試圖分配一個結構體, 通過傳遞socket_id, 即node id獲得本地內存, 並且以Cache行對齊。

 

第三章 並行計算

多核並行計算的吞吐率隨核數增加而線性擴展, 可並行處理部分佔整個任務比重越高, 則增長的斜率越大。 帶着這個觀點來讀DPDK, 很多實現的初衷就豁然開朗。 資源局部化、 避免跨核共享、 減少臨界區碰撞、 加快臨界區完成速率(後兩者涉及多核同步控制, 將在下一章中介紹)等, 都不同程度地降低了不可並行部分和併發干擾部分的佔比。

親和性

線程獨佔:

DPDK通過把線程綁定到邏輯核的方法來避免跨核任務中的切換開銷, 但對於綁定運行的當前邏輯核, 仍然可能會有線程切換的發生, 若希望進一步減少其他任務對於某個特定任務的影響, 在親和的基礎上更進一步, 可以採取把邏輯核從內核調度系統剝離的方法。Linux內核提供了啓動參數isolcpus。 對於有4個CPU的服務器, 在啓動的時候加入啓動參數isolcpus=2, 3。 那麼系統啓動後將不使用CPU3和CPU4。 注意, 這裏說的不使用不是絕對地不使用, 系統啓動後仍然可以通過taskset命令指定哪些程序在這些核心中運行。

DPDK的線程基於pthread接口創建, 屬於搶佔式線程模型, 受內核調度支配。 DPDK通過在多核設備上創建多個線程, 每個線程綁定到單獨的核上, 減少線程調度的開銷, 以提高性能。

DPDK的線程可以作爲控制線程, 也可以作爲數據線程。 在DPDK的一些示例中, 控制線程一般綁定到MASTER核上, 接受用戶配置, 並傳遞配置參數給數據線程等; 數據線程分佈在不同核上處理數據包。

EAL中提供lcore來提供EAL線程,可以與核進行綁定。

單指令多數據SIMD

DPDK中的memcpy就利用到了SSE/AVX的特點。 比較典型的就是rte_memcpy內存拷貝函數。 內存拷貝是一個非常簡單的操作, 算法上並無難度, 關鍵在於很好地利用處理器的各種並行特性。 當前Intel的處理器(例如Haswell、 Sandy Bridge等) 一個指令週期內可以執行兩條Load指令和一條Store指令, 並且支持SIMD指令(SSE/AVX) 來在一條指令中處理多個數據, 其Cache的帶寬也對SIMD指令進行了很好的支持。 因此, 在rte_memcpy中, 我們使用了平臺所支持的最大寬度的Load和Store指令(Sandy Bridge爲128bit, Haswell爲256bit) 。 此外, 由於非對齊的存取操作往往需要花費更多的時鐘週期, rte_memcpy優先保證Store指令存儲的地址對齊, 利用處理器每個時鐘週期可以執行兩條Load這個超標量特性來彌補一部分非對齊Load所帶來的性能損失。 更多信息可以參考[Ref3-3] 。

例如, 在Haswell上, 對於大於512字節的拷貝, 需要按照Store地址進行對齊。

/**

* Make store aligned when copy size exceeds 512 bytes

*/

dstofss = 32 - ((uintptr_t)dst & 0x1F);

n -= dstofss;

rte_mov32((uint8_t *)dst, (const uint8_t *)src);

src = (const uint8_t *)src + dstofss;

dst = (uint8_t *)dst + dstofss;

在Sandy Bridge上, 由於非對齊的Load/Store所帶來的的額外性能開銷非常大, 因此, 除了使得Store對齊之外, Load也需要進行對齊。 在操作中, 對於非對齊的Load, 將其首尾未對齊部分多餘的位也加載進來,因此, 會產生比Store指令多一條的Load。

第四章 同步互斥機制

提供了一套自己的內存屏障、互斥、讀寫鎖、SPIN鎖、無鎖環形隊列

 

第五章 報文轉發

報文處理模塊劃分

 

淺色和陰影部分都是對應模塊和硬件相關的,所以提升這部分性能最佳的選擇是儘量多的選擇網卡上的或設備芯片提供的網絡特定功能相關的卸載的特性,深色軟件部分可以通過提高算法的效率和結合CPU相關的並行指令來提升網絡性能,瞭解網絡處理模塊的基本組成部分後,我們再來看看不同的轉發框架如何讓這些模塊協同工作完成網絡包的處理的

轉發框架介紹

  2.1 流水線模型(pipeline)

  pipeline 借鑑與工業上的流水線模型,將整個功能拆分成多個獨立的階段,不同階段通過隊列傳遞產品。這樣對於一些CPU密集和I/O密集的應用,將I/O密集的操作放在另一個微處理器引擎上執行。通過過濾器可以分爲不同的操作分配不同的線程,通過隊列匹配兩個速度,達到最好的併發,

  

  我們可以看到圖中,TOP(Task Optimized Processor)單元,每個TOP單元都是對特定的事物進行優化處理的特殊微單元

  2.2  run to completion 模型

  這個模型是DPDK針對一般的程序的運行方法,一個程序分爲幾個不同的邏輯功能,幾個邏輯功能會在一個CPU的核上運行,我們下面看下模型的視圖

  

    這個模型沒有對報文特殊處理的的運算單元,只有兩個NP核, 兩個NP核利用已燒錄的微碼進行報文處理

  

  2.3 轉發模型對比

  從run to completion的模型中,我們可以清楚地看出,每個IA的物理核都負責處理整個報文的生命週期從RX到TX,這點非常類似前面所提到的AMCC的nP核的作用。在pipeline模型中可以看出,報文的處理被劃分成不同的邏輯功能單元A、B、C,一個報文需分別經歷A、B、C三個階段,這三個階段的功能單元可以不止一個並且可以分佈在不同的物理核上,不同的功能單元可以分佈在相同的核上(也可以分佈在不同的核上),從這一點可以看出,其對於模塊的分類和調用比EZchip的硬件方案更加靈活。

  

  兩個的優缺點:

  

  

轉發算法

  除了良好的轉發框架之外,轉發中很重要的一部分內容就是對於報文字段的匹配和識別,在DPDK中主要用到了精確匹配(Exact Match)算法和最長前綴匹配(Longest Prefix Matching,LPM)算法來進行報文的匹配從而獲得相應的信息。精確匹配主要需要解決兩個問題:進行數據的簽名(哈希),解決哈希的衝突問題,DPDK中主要支持CRC32和J hash。

  最長前綴匹配(Longest Prefix Matching,LPM)算法是指在IP協議中被路由器用於在路由表中進行選擇的一個算法。當前DPDK使用的LPM算法就利用內存的消耗來換取LPM查找的性能提升。當查找表條目的前綴長度小於24位時,只需要一次訪存就能找到下一條,根據概率統計,這是佔較大概率的,當前綴大於24位時,則需要兩次訪存,但是這種情況是小概率事件。

ACL庫利用N元組的匹配規則去進行類型匹配,提供以下基本操作:

  

  Packet distributor(報文分發)是DPDK提供給用戶的一個用於包分發的API庫,用於進行包分發。主要功能可以用下圖進行描述:

  

 

精確匹配算法

相當於使用了Hash算法

最長匹配算法

使用了兩級表。針對IPv4路由查找,一級是2^24個條目,二級是2^8的條目。用空間換時間。

 

第六章 PCIe與包處理I/O

Mbuf與Mempool

數據結構rte_mbuf可以承載網絡數據包buffer或者通用控制消息buffer(由CTRL_MBUF_FLAG指示)。 也可以擴展到其他類型。 rte_mbuf頭部結構儘可能小,目前只使用兩個緩存行,最常用的字段位於第一個緩存行中

 

爲了存儲數據包數據(報價協議頭部), 考慮了兩種方法:

 

在單個存儲buffer中嵌入metadata,後面跟着數據包數據固定大小區域

爲metadata和報文數據分別使用獨立的存儲buffer。

第一種方法的優點是他只需要一個操作來分配/釋放數據包的整個存儲表示。 但是,第二種方法更加靈活,並允許將元數據的分配與報文數據緩衝區的分配完全分離。

 

DPDK選擇了第一種方法。 Metadata包含諸如消息類型,長度,到數據開頭的偏移量等控制信息,以及允許緩衝鏈接的附加mbuf結構指針。

 

用於承載網絡數據包buffer的消息緩衝可以處理需要多個緩衝區來保存完整數據包的情況。 許多通過下一個字段鏈接在一起的mbuf組成的jumbo幀,就是這種情況。

 

對於新分配的mbuf,數據開始的區域是buffer之後 RTE_PKTMBUF_HEADROOM 字節的位置,這是緩存對齊的。 Message buffers可以在系統中的不同實體中攜帶控制信息,報文,事件等。 Message buffers也可以使用起buffer指針來指向其他消息緩衝的數據字段或其他數據結構。

Fig. 6.1 An mbuf with One Segment

 

多核CPU訪問同一個內存池或者同一個環形緩存區時, 因爲每次讀寫時都要進行Compare-and-Set操作來保證期間數據未被其他核心修改,所以存取效率較低。 DPDK的解決方法是使用單核本地緩存一部分數據, 實時對環形緩存區進行塊讀寫操作, 以減少訪問環形緩存區的次數。 單核CPU對自己緩存的操作無須中斷, 訪問效率因而得到提高。 當

然, 這個方法也並非全是好處: 該方法要求每個核CPU都有自己私用的緩存(大小可由用戶定義, 也可爲0, 或禁用該方法) , 而這些緩存在絕大部分時間都沒有能得到百分之百運用, 因此一部分內存空間將被浪費。

 

第七章 網卡性能優化

DPDK的輪詢模式

DPDK採用了輪詢或者輪詢混雜中斷的模式來進行收包和發包, 此前主流運行在操作系統內核態的網卡驅動程序基本都是基於異步中斷處理模式。

DPDK的混合中斷輪詢機制是基於UIO或VFIO來實現其收包中斷通知與處理流程的。 如果是基於VFIO的實現, 該中斷機制是可以支持隊列級別的, 即一個接收隊列對應一箇中斷號, 這是因爲VFIO支持多MSI-X中斷號。 但如果是基於UIO的實現, 該中斷機制就只支持一箇中斷號, 所有的隊列共享一箇中斷號。

網卡I/O性能優化

使用Burst收發包:把收發包複雜的處理過程進行分解,打散成不同的相對較小的處理階段,把相鄰的數據訪問、相似的數據運算集中處理。儘可能減少內存或低一級的處理器緩存的訪問次數。即一次完成多個數據包的收發。

平臺優化及其配置調優

不同的硬件平臺,可以做對應的配置。

 

第八章 流分類與多隊列

Linux內核對多隊列的支持

  1. 多隊列對應的結構:Linux的網卡由結構體net_device表示,一個該結構可以對應多個可以調度的數據包發送隊列,數據包的實體在內核中以結構體sk_buff(skb)表示

  2. 接收端:網卡驅動程序爲每個接收隊列設定相應的中斷號,通過中斷的均衡處理,或者設置中斷的親和性,從而實現隊列綁定到不同的核。

  3. 發送端:Linux提供了較爲靈活的隊列選擇機制。dev_pick_tx用於選取發送隊列,他可以是driver定製的策略,也可以根據隊列優先級選取,按照hash做均衡。將隊列分配給某個或某幾個CPU處理,這樣就可以減少鎖競爭。

  4. 收發隊列一般會被綁在同一個中斷上。如果從收隊列1收上來的包從發隊列1發出去,cache命中率高,效率也會高。

對於單隊列的網卡設備,就需要用軟件來均衡流量。

DPDK與多隊列

DPDK提供了一系列以太設備的API,其Packt I/O機制具有與生俱來的多隊列支持功能,可以根據不同的平臺或者需求,選擇需要使用的隊列數目,並可以很方便地使用隊列,指定隊列發送或接收報文。

DPDK的隊列管理機制還可以避免多核處理器中的多個收發進程採用自旋鎖產生的不必要的等待。

以run to completion模型爲例,可以從核、內存與網卡隊列之間的關係來理解DPDK是如何利用網卡多隊列技術帶來性能的提升。

  • 將網卡的某個接收隊列分配給某個核,從該隊列中收到的所有報文都應當在該指定的核上處理結束

  • 從覈對應的本地存儲中分配內存池,接收報文和對應的描述符都位於該內存池

  • 爲每個核分配一個單獨的發送隊列,發送報文和對應的報文描述符都位於該核和發送隊列對應的本地內存池中。

RSS

Receive-Side Scaling:接收方擴展,和硬件相關,需要有網卡的硬件進行支持,RSS把數據包分配到不同的隊列中,其中哈希值的計算公式在硬件中完成,也可以定製修改。關鍵字通常是五元組相關。

 

Flow Derector

由Intel公司提出的根據包的字段精確匹配,將其分配到某個特定隊列的技術

 

第九章 硬件加速與功能卸載

需要網卡支持

 

第十章 X86平臺上的I/O虛擬化

DPDK支持半虛擬化的前端virtio和後端vhost,並且對前後端都有性能加速的設計。對於I/O透傳,DPDK可以直接在客戶機裏使用,就像在宿主機裏,直接接管物理設備,進行操作。

KNI圖片:

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章