執行人: LULser0204
專題解說影片
cheezad
第一段有一個小錯字 (exameple),已修正
謝謝
eleanorLYJ
需要更多的初步介紹讓人能更快看懂你要做甚麼,例如第一個 todo,實驗目的為何?還有 MutexShootout 專案的目的是什麼?雖然你影片有用一句話說明,但仍建議可以增加敘述。
好的
建立 POSIX Thread 部分相容且輕量級的實作。
重現實驗並紀錄問題
該實驗主要是比較 pthread 和 futex 的表現,其中 pthread 的部分使用 skinny_mutex 來實作
實作輕量級的 Mutex Lock
其中 futex 是放在 perf-test/main.c 的程式碼,pthread 則是 結合了 skinny_mutex 也可稱作 Low-memory-footprint mutexes for pthreads
闡述 skinny_mutex 要解決什麼問題,以及何以稱為「輕量級」。
skinny_mutex 目的是在不犧牲效能的前提下,減少佔用的記憶體空間。用於取代 pthread api 提供的 mutex,特別是當 mutex 保護的是小型資料結構。
為何稱為「輕量級」呢? 因為標準的 pthread_mutex_t 佔用的記憶體空間( 24bytes on 32-bit machine and 40bytes on 64-bit machines )較多;而 skinny_mutex 只佔用一個指標大小的空間
一開始我嘗試在 example 的makefile 跳出
這個問題是 ThreadSanitizer (TSan) 出現了意外的記憶體映射。
參考 ThreadSanitizer: unexpected memory mapping,我一開始認為是我的 GCC 版本問題,但更新後還是碰到相同的問題。後來查到 FATAL: ThreadSanitizer: unexpected memory mapping when running on Linux Kernels 6.6+ 的討論,只要執行 sudo sysctl vm.mmap_rnd_bits=28
就可以正確執行了。
因為 ThreadSanitizer 需要對程式的記憶體操作進行精確的追蹤和檢測。如果記憶體地址的隨機化程度太高,可能會導致 ThreadSanitizer 無法正確預測和管理記憶體映射,通過 vm.mmap_rnd_bits=28
減少了地址的隨機性。
可以觀察到 futex 大多時候表現優於 pthread 的實作
該實驗主要是測試解決 Priority Inversion 的不同方法。
先使用 Normal mutex 重現 Priority Inversion,分別是用 Priority Inheritance mutex、Priority Protection mutex 來解決
Priority Inheritance mutex :假設低優先權的 thread 先取得 lock,當高優先權的 thread 想要取得 lock 時,發現 lock 已被低優先權的持有,此時高優先權的 thread 會讓目前持有 lock 的 thread 先暫時提高優先權,等待其釋放 lock 後再將優先權降回原本
Priority Protection mutex :每個 mutex 建立時都會被賦予一個 prioceiling 的值(比所有可能獲得該 mutex thread 優先權都還要高的值)。當 thread 取得 lock 時,該優先權會被提升到 prioceiling ,確保不會被低優先權搶佔 ; 另一個實作方式是 當 thread 取得 mutex 時,將持有 mutex 的 thread 提高到該排程策略的最高優先級,只是可能會過度提升,導致其他執行重要任務的 thread 無法使用 CPU 資源
我在執行 建立 PThread 相容實作 內 測試程式 時,在我輸入 make test
後,總是回報 segmentation fault
,我有嘗試將程式內 muprint 部分改成 pthread 仍然有相同的問題。於是我嘗試用 gdb 觀察是斷在什麼地方,設定了三個 break point (在 thread_func_normal、thread_func_recursive、main ) ,除了第一條 thread 能夠正確執行 muthread_t self = muthread_self()
外,其他幾條執行都會觸發錯誤。
另外我也有修改 makefile 觀察是否只有 test01 有這問題,然而只有部分幾個能正常執行。
我後來在另一台電腦,Linux 系統資訊 :
可以正常的執行,我觀察兩個 GDB 執行狀況,在 20.04 版本跑得會顯示 "Trying to acquire the mutex succeeded"
另外我使用 Valgrind 分別對 ubuntu 20.04 和 ubuntu 22.04 觀察 Segmentation fault 原因,此為 ubuntu 22.04
此為 ubuntu 20.04 ,該環境也有 invalid read of size 只是在 22.04 的 size 大小是 1 ,20.04 size 大小是 4 (節錄部分,可以完全執行)
最後實驗結果 (只擷取部分) [ priority-inversion、priority-inversion-PI、priority-inversion-PP ]
在 ubuntu 20.04 glibc 版本是 2.31 ,而在 ubuntu 22.04 glibc 版本是 2.35 ,應該是某些函數 定義上不同或是兩個版本對於記憶體配置的方式不同,使得在 ubuntu 20.04 上即便有發生 Segmentation fault 但不至於終止。
不要使用 spoiler
標示,充分揭露你的想法、嘗試、發現,和如何解決問題。
好
嘗試用
git reset
指定到某些功能導向修改的 commit,執行對應的測試,觀察其行為並修正。
MutexShootout 專案的目的是為了測試不同種的 mutex 效果,其中大多 mutex 是在 windows 上才有的 (作者也有提供 FreeBSD 的)
該實驗的目的是使用這些作者實作出來的 mutex 帶入 perf-test 的測試環境,用以比較 futex 、pthread、以及好幾種在 windows 環境下的 mutex
在這個專案中,各個檔案的作用大致上如下:
嘗試合併時,碰到的第一個問題是命名和 boost 庫裡面的 load 衝突,所以將使用到 stdatomic.h 函數的都改成用 C++11 所定義的 atomic
觀察 boost 內對於 load 定義在 boost/serialization/nvp.hpp
參考官方文件
其中 Archive 的定義 : An archive is defined by two complementary classes. One is for saving data while the other is for loading it.
而 nvp 參考 官方文件 指的是 "Name-Value Pair" 封裝了資料成對操作的功能
directory 是「目錄」,而非 folder,前者是 UNIX 用語。
data 是「資料」,而非「數據」
收到
我嘗試將除了 main.cpp 以外的檔案放入 perf-test 的目錄,然後參考 main.cpp 內的 run_benchmark 改成 perf-test 的測試方法
目前只有測試過在 Linux 環境下執行,還需要嘗試看看windows環境的
因為作者在 main.c 內有一段以及 readme
所以可以觀察到我在 Ubuntu 環境下跑,std (futex) 和 boost (也是用futex) 的表現差不多,然後兩個都比 thread 表現還要好
備註:threadcount 為 4 build/plot.py 可以設定數量
完整變更 : commit feefe75
注意用語:
嘗試在 Windows 上執行
無法在 windows 上使用 pthread.h 提供的 api ,有幾個方法解決
1.改用 windows.h : windows 此為 windows 提供的 api
2.改用 C++11 thread 提供的api
3.或者是另外安裝 pthread.h :具體方法可以參考 在VS2015下建立執行thread的環境安裝教學 ,只是 dll 要放 x64 資料夾的
如果想使用 boost library ,然後使用的是 Visual studio 2022 會發現一直無法成功 build,我卡在這邊卡超久,後來終於在官方的 No support for msvc-toolset 14.4x (VS 2022, 17.10.x) 找到有人和我遇到一樣的問題
因為 b2 的建置腳本在 Visual Studio 的 " 版本判斷 " 腳本在 (
tools/build/src/tools/msvc.jam
)裡面,是把 14.3 當成 Visual Studio 2022。但是 VS2022 最新版已把版本推到 14.40 了,結果就沒辦法正確判斷版本
英雄所見略同,恭喜你提升自己的視野
然後,這是在 windows 上的執行結果,分別是 "std:mutex (VS 2022)"、"srw_mutex"、"cs_mutex_4K"、"cs_mutex_nospin"、"boost::mutex"
這是將 windows 上和 linux 上的 mutex 進行比較
可以觀察到 Linux 下的 mutex 表現都比 windows 的好