並行編程——開源並發庫、無鎖數據結構


1  一些資源

http://openmp.org/wp/  openmp 開放標准的並行程序指導性注釋,沒用過

http://software.intel.com/zh-cn/articles/parallelization-using-intel-threading-building-blocks-intel-tbb  intel tbb ,Intel的C++多線程庫,沒有用過,有人說性能很不好

https://code.google.com/p/nbds/  無鎖數據結構庫,關鍵是針對緩存做了優化,需要注意的是里邊的哈希表是沒有刪除的,說多了都是淚

http://mcg.cs.tau.ac.il/projects/hopscotch-hashing-1 並發的hopscotch哈希表實現

da-data.blogspot.nl/2013/03/optimistic-cukoo-hashing-for.html 並發的cukoo實現,查找非常快,但增加和刪除目前是大鎖,作者說以后會推出無鎖的增加和刪除,不知道什么時候出來

http://ww2.cs.mu.oz.au/~astivala/paralleldp/ 實現了無鎖的基於數組的哈希表,無鎖的基於鏈表的哈希表,對比了多種實現的性能,無鎖實現仍然是沒有刪除,另外,無鎖實現沒有針對緩存做優化
http://dpdk.org/  rte_ring.c 實現了無鎖的生產者消費者隊列

另外,據說apache protable runtime 里邊有很多lock-free算法,Windows里的Interlocked系列函數內部實現也用到了很多lock-free算法,沒有驗證過。

 上述代碼里,詳細調試過的有nbds的無鎖hashtable, 用它構造了一個哈希表作為流表,與基於DPDK example的一種哈希表+dpdk rwlock 的實現做L3轉發性能對比,發現不刪流的情況下性能差不多,當然測試是在沖突率不是很高的情況下測試的。

2. 一次測試

2.1  測試平台

測試在一台intel E5-2658 上進行,這款CPU有兩個物理CPU,每個物理CPU有8個核,每個核有兩個核線程。測試只使用到一顆物理CPU,只用到core1~core8,發包和統計工具是testcenter發包儀器,使用兩塊萬兆網卡對發udp包。

2.2  測試過程

1)    DPDK 示例程序examples 里有 l2fwd 示例程序,測試程序在l2fwd的基礎上改寫。

如圖,l2fwd 只有收包和發包兩個步驟,測試程序增加了解碼和查表(增加節點、拷貝mac)的操作。

1) 測試時,固定2個core線程負責兩個網卡的收包和發包,中間的解碼+會話表處理靈活配置核心,測試對比了 2個,4個,6個核線程的情況

2) 哈希表部分API 使用函數指針做了一個抽象層(lookup,insert,delete),具體實現替換為不同的哈希表實現

2.3  哈希算法

1) 第一種哈希使用DPDK librte_hash/rte_fbk_hash.c 增加rte_rwlock 實現,在原有哈希算法基礎上,每個bucket增加一個rwlock, lookup 的時候需要獲取讀鎖,返回前釋放。Insert 需要先獲取寫鎖,然后lookup一遍沒有相同值再插入,返回前釋放寫鎖,delete 也需要獲取寫鎖。

2) 第二種哈希使用nbds 的 hashtable.c 實現,在原有哈希算法基礎上,將key,value 的真實值替換為 DPDK 的mempool 實現,將所有內存的申請替換為 DPDK 的rte_malloc實現。

2.4  測試結果

3) 簡單測試發現,隨着中間工作核線程數目增加,性能有明顯提升

4) 多次反復測試發現,兩種哈希實現性能相差不大。

5) Nbds 沒有實現真正的delete算法,研究中發現,大部分開源的無鎖結構都沒有實現刪除算法,刪除算法會導致“狀態爆炸”即中間可能的狀態太多導致正確性很難證明。

 

結論:

a, 對於哈希表這種操作相對復雜的結構,加上要考慮多核平台的內存模型,無鎖的高效穩定實現非常難,不要自己實現這樣的結構。

b. 基於自旋鎖/讀寫鎖實現的哈希表性能可以接受

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM