文章目錄
- 1 PMEM 底層架構
- 2 PMEM 邏輯架構
- 3 ipmctl 建立 不同模式的 region
- 3.1 安裝
- 3.2 建立AppDirect mode的region
- 3.3 建立 Memory Mode模式
- 3.4 建立 混合模式
- 3.5 檢視建立的結果
- 4 ndctl 建立不同類型的 namespaces
- 4.1 安裝
- 4.2 建立/删除 一個任意類型的namespace
- 4.3 指定類型 建立 namespaces
- 4.4 變更已有namespace 類型
- 5 namespace 的應用
- 6 fio測試 fsdax 和 devdax
- 7 參考
之前總結過一篇文章來總體介紹optane 持久記憶體 的架構以及其 程式設計模式
Intel Optane 持久記憶體概覽,這裡主要是記錄一下針對Optane 持久記憶體 管理工具的使用方式,通過這一些工具的使用能夠更為清晰得了解NVM(pmem) 的底層架構。
下文中提到的建立指令都是在 centos上進行的,不過ipmctl/ndctl/fio 這種基礎指令使用方式都是一樣的,可能就是安裝這一些工具的指令和其他的系統有一些差異。
1 PMEM 底層架構
PMEM 的存儲媒體是 3D Xpoint ,其底層存儲單元是PCM(phase change memory 即相變記憶體),這也是pmem 實體存儲和傳統的 NAND SSD最大的差異。但其和Optane NVMe SSD 最大的差異則是實體接口的不同,一個是PCIe接口(nvme ssd),一個是DIMM 接口(pmem)。 關于 NAND和3D XPoint 的實體差異可以通過從NMOS 和 PCM 底層存儲單元 來看NAND和3D XPoint的本質差別 來了解一下。
那我們先看看 PMEM 的底層實體形态,這是我們的NUMA 下的cpu和記憶體插槽的分布。

其中藍色區域是DRAM 插槽,黑色插槽可以插PMEM 存儲媒體。
需要注意的是:
- 對于每一個CPU而言,PMEM 媒體應該插在每組(一藍一黑兩個算一組)靠近CPU的那一個槽中,即黑色的插槽;另一個槽插入DRAM。
- 使用App Direct Mode 的時候每組槽中的PMEM 可以不搭配DRAM;使用Memory Mode 的時候,每組槽中的PMEM必須搭配DRAM,否則無法配置成MemoryMode 模式使用。
- 必須要確定每個CPU兩邊的 pmem 媒體個數相等;而不同組 CPU 各自的PMEM數量可以不同,造成的結果就是兩個region 顯示的容量不同。
檢視目前系統DRAM 和 pmem 的拓撲結構
# 需要root 使用者執行
$ ipmctl show -topology
DimmID | MemoryType | Capacity | PhysicalID| DeviceLocator
================================================================================
0x0001 | Logical Non-Volatile Device | 126.375 GiB | 0x0021 | DIMM 6
0x0011 | Logical Non-Volatile Device | 126.375 GiB | 0x0023 | DIMM 4
0x0101 | Logical Non-Volatile Device | 126.375 GiB | 0x0027 | DIMM 7
0x0111 | Logical Non-Volatile Device | 126.375 GiB | 0x0029 | DIMM 9
0x1001 | Logical Non-Volatile Device | 126.375 GiB | 0x002d | DIMM 18
0x1011 | Logical Non-Volatile Device | 126.375 GiB | 0x002f | DIMM 16
0x1101 | Logical Non-Volatile Device | 126.375 GiB | 0x0033 | DIMM 19
0x1111 | Logical Non-Volatile Device | 126.375 GiB | 0x0035 | DIMM 21
N/A | DDR4 | 32.000 GiB | 0x0020 | DIMM 5
N/A | DDR4 | 32.000 GiB | 0x0022 | DIMM 3
N/A | DDR4 | 32.000 GiB | 0x0024 | DIMM 1
N/A | DDR4 | 32.000 GiB | 0x0026 | DIMM 8
N/A | DDR4 | 32.000 GiB | 0x0028 | DIMM 10
N/A | DDR4 | 32.000 GiB | 0x002a | DIMM 12
N/A | DDR4 | 32.000 GiB | 0x002c | DIMM 17
N/A | DDR4 | 32.000 GiB | 0x002e | DIMM 15
N/A | DDR4 | 32.000 GiB | 0x0030 | DIMM 13
N/A | DDR4 | 32.000 GiB | 0x0032 | DIMM 20
N/A | DDR4 | 32.000 GiB | 0x0034 | DIMM 22
N/A | DDR4 | 32.000 GiB | 0x0036 | DIMM 24
2 PMEM 邏輯架構
這裡介紹兩種 用于組織插在DIMM 插槽之上的邏輯分離存儲形态
region
和
namespace
。
- region : 用來組織pmem module的邏輯概念。一個region 中可以有一個或者多個pmem module(插在DIMM 上的pmem 存儲媒體)。目前支援的region 模式有兩種: interleave 和 non-interleave 的;其中interleave 模式是一個region 可以跨目前CPU的多個 DIMM,non-interleave 模式則是一個region 隻能在一個DIMM 上。
- namespace: 是一段 on pmem 的 可連續尋址的位址範圍,類似于硬碟分區 或者 SCSI的邏輯單元(LUN) 或者 NVMe 的namespace。隻有在 建立的region 模式是 AppDirect 模式時才能在region 上建立namespace。
除了以上兩個主要的 對pmem 操作的邏輯分區之外,還有幾個概念需要了解:
- Label : 每一個pmem module(pmem 存儲媒體) 都包涵一個 Label Storage Area(LBA) 區域,用來存儲namespace 的中繼資料配置。這樣,就可以在region 上建立不同類型的namespace 來支援針對pmem 的不同通路模式。
- DAX:Direct Access。pmem 在AppDirect 模式下 通過namespace 建立的 不同類型的裝置可以為使用者提供 device access 以及 fs access的通路模式。在fs access 下 通過支援DAX 模式的檔案系統(xfs, ext4, on windows ntfs)來 最大程度得縮短通路pmem的路徑,通路的過程都是通過mmap 來進行的,能夠by-pass page-cache, i/o subsystem 以及 中斷和上下文切換。
下面是 non-interleaved regions 和 interleaved region 以及 on interleave region下的namespaces。
關于pmem 程式設計架構形态如下:
其中namespace 支援的四種模式 可以比對到上面針對 NVM-DIMMS 的通路形态中了:
-
: 就是一個記憶體盤的形态來直接通路,不支援DAX 模式的通路。raw
-
: 可以作為一個傳統的塊裝置 以及 on 塊裝置的檔案系統,且這個檔案系統不限制類型(任意檔案系,不需要dax支援)。可以允許按位元組通路,但是不能保證通路的原子性。sector
-
: 需要 pmem-aware filter system支援,即支援dax 挂載的檔案系統,這樣該namespace 可以通過标準檔案接口讀寫 ,同時也支援 通過pmdk 來通路。這個namespace 類型 是大多數的appdirect 模式下的持久記憶體使用方式。fsdax
-
: 允許通過 mmap 直接将指定容量的 pmem 媒體映射到記憶體進行通路,這個devdax 模式的namespace 被建立出來之後不能像其他的塊裝置一樣建立dax檔案系統,它被映射出來之後是一個字元裝置形态(/dev/dax3.0 這種)。這種模式一般用作虛拟機,RDMA 以及 大頁映射。devdax
到此,我們大體就清楚了PMEM 的邏輯架構 ,如何通過 邏輯 region 組織實體上的 DIMMS,以及如何在邏輯region之上建構資料分離存儲的namespaces。
接下來我們看看如果通過 pmem的 management tools 來組合這一些邏輯架構,建構豐富的pmem 使用形态。
3 ipmctl 建立 不同模式的 region
如果你的環境中已經有了pmem裝置(直接可用的檔案系統形态的pmem),可以直接跳過這一個工具的介紹,看下一個
ndctl
工具。
3.1 安裝
這個工具是建構pmem region的底層工具,建議安裝的時候讓其版本在
2.x
及以上。
直接源碼編譯安裝即可:
git clone https://github.com/pmem/ndctl.git
cd ndctl
./autogen.sh
./configure CFLAGS='-g -O2' --prefix=/usr --sysconfdir=/etc --libdir=/usr/lib64
make
make check
sudo make install
安裝完成之後記得更新一下
PATH
,否則指令行會找不到這個工具
export PATH=$PATH:/usr/local/bin
。
需要注意一個問題,就是如果你的ipmctl 最開始的版本比較低,可能會導緻最後建立的interleaved 模式的 region 無法建立混合模式的namespaces,這個issue 解決可以參考 https://github.com/pmem/ndctl/issues/181。
關于ipmctl 工具的使用都需要在root 模式下執行
3.2 建立AppDirect mode的region
- 檢視目前已有mode
# ipmctl show -memoryresources
MemoryType | DDR | PMemModule | Total
==========================================================
Volatile | 384.000 GiB | 0.000 GiB | 384.000 GiB
AppDirect | - | 1008.000 GiB | 1008.000 GiB
Cache | 0.000 GiB | - | 0.000 GiB
Inaccessible | 0.000 GiB | 3.377 GiB | 3.377 GiB
Physical | 384.000 GiB | 1011.377 GiB | 1395.377 GiB
上面這個是AppDirectmode
- 建立AppDirect mode,這個指令會将目前的所有容量預設建立出interleaved mode的 region
# ipmctl create -goal PersistentMemoryType=AppDirect
The following configuration will be applied:
SocketID | DimmID | MemorySize | AppDirect1Size | AppDirect2Size
==================================================================
0x0000 | 0x0001 | 0.000 GiB | 126.000 GiB | 0.000 GiB
0x0000 | 0x0011 | 0.000 GiB | 126.000 GiB | 0.000 GiB
0x0000 | 0x0101 | 0.000 GiB | 126.000 GiB | 0.000 GiB
0x0000 | 0x0111 | 0.000 GiB | 126.000 GiB | 0.000 GiB
0x0001 | 0x1001 | 0.000 GiB | 126.000 GiB | 0.000 GiB
0x0001 | 0x1011 | 0.000 GiB | 126.000 GiB | 0.000 GiB
0x0001 | 0x1101 | 0.000 GiB | 126.000 GiB | 0.000 GiB
0x0001 | 0x1111 | 0.000 GiB | 126.000 GiB | 0.000 GiB
Do you want to continue? [y/n] y
Created following region configuration goal
SocketID | DimmID | MemorySize | AppDirect1Size | AppDirect2Size
==================================================================
0x0000 | 0x0001 | 0.000 GiB | 126.000 GiB | 0.000 GiB
0x0000 | 0x0011 | 0.000 GiB | 126.000 GiB | 0.000 GiB
0x0000 | 0x0101 | 0.000 GiB | 126.000 GiB | 0.000 GiB
0x0000 | 0x0111 | 0.000 GiB | 126.000 GiB | 0.000 GiB
0x0001 | 0x1001 | 0.000 GiB | 126.000 GiB | 0.000 GiB
0x0001 | 0x1011 | 0.000 GiB | 126.000 GiB | 0.000 GiB
0x0001 | 0x1101 | 0.000 GiB | 126.000 GiB | 0.000 GiB
0x0001 | 0x1111 | 0.000 GiB | 126.000 GiB | 0.000 GiB
A reboot is required to process new memory allocation goals.
# reboot -n
如果 想建立
non-interleaved
模式的region,則可以執行指令:
ipmctl create -goal PersistentMemoryType=AppDirectNotInterleaved
3.3 建立 Memory Mode模式
其中
MemoryMode
是一個百分比,如果是100的話則表示目前所有的pmem module 容量都會作為memory mode。
# ipmctl create -goal MemoryMode=100
# reboot
重新開機之後,檢視
free -h
時能夠看到記憶體的容量已經加上了所有的 pmem module 的容量了
3.4 建立 混合模式
建立記憶體模式的時候 有一個參數
MemoryMode
用來指定百分比,顯而易見 我們可以在一個機器上讓一部分的容量作為AppDirect 模式。
比如配置 50% 的容量為 memory mode 即可
# ipmctl create -goal MemoryMode=50
以上過程中如果想要清理所有的 config,可以通過
ipmctl delete –goal
。
3.5 檢視建立的結果
- 檢視 goal
ipmctl show -goal
- 檢視regions
ipmctl show -region
- 檢視記憶體資源情況
ipmctl show -memoryresources
- 檢視 dimms 分布
ipmctl show -dimms
4 ndctl 建立不同類型的 namespaces
ndctl 的建立/删除/更新 namespace 需要root權限,檢視namepace 資訊則不需要root
4.1 安裝
ndctl 的安裝則不是很友善,如果系統庫不全的話可能遇到的問題會比較多,我将我的安裝完整過程貼下來:
- 前置庫安裝
sudo yum install autoconf pkg-config libndctl-devel libdaxctl-devel pandoc -y
- 安裝過程
git clone https://github.com/pmem/ndctl.git
cd ndctl
git checkout v71 # 目前的最新版本
./autogen.sh
Activated pre-commit hook.
GIT_VERSION = 71
sh: aclocal: command not found
autoreconf: aclocal failed with exit status: 127 # 執行失敗
----------------------------------------------------
# 解決
sudo yum install automake libtool -y
autoreconf -ivf
# 執行成功
$ ./autogen.sh
----------------------------------------------------------------
Initialized build system. For a common configuration please run:
----------------------------------------------------------------
./configure CFLAGS='-g -O2' --prefix=/usr --sysconfdir=/etc --libdir=/usr/lib64
# 執行./configure
./configure CFLAGS='-g -O2' --prefix=/usr --sysconfdir=/etc --libdir=/usr/lib64
...
checking for a sed that does not truncate output... (cached) /usr/bin/sed
checking for asciidoctor... missing
configure: error: asciidoctor needed to build documentation # 執行失敗
----------------------------------------------------
# 解決
sudo yum install asciidoctor -y
# 重新執行 ./configure
./configure CFLAGS='-g -O2' --prefix=/usr --sysconfdir=/etc --libdir=/usr/lib64
...
checking for KMOD... no
configure: error: Package requirements (libkmod) were not met:
No package 'libkmod' found
Consider adjusting the PKG_CONFIG_PATH environment variable if you
installed software in a non-standard prefix # 執行失敗
----------------------------------------------------
#解決
sudo yum install kmod kmod-devel -y
# 再次重新執行 ./configure
./configure CFLAGS='-g -O2' --prefix=/usr --sysconfdir=/etc --libdir=/usr/lib64
...
configure: error: Package requirements (uuid) were not met:
No package 'uuid' found #執行失敗
----------------------------------------------------
#解決
sudo yum install libuuid-devel json-c-devel -y
# 執行./configure 成功,生成 Makefile
./configure CFLAGS='-g -O2' --prefix=/usr --sysconfdir=/etc --libdir=/usr/lib64
# 安裝ndctl
make && sudo make install
4.2 建立/删除 一個任意類型的namespace
- 檢視已有的namespaces
能夠展示所有建立好的可用的 namespace 以及其所屬的 region資訊完整列印出來。ndctl list --namespaces --regions
- 建立一個namespace,如果不指定namespace 類型的話預設建立的是raw 類型
ndctl create-namespace --force
- 删除一個namespace 的話 可以通過
或者 不指定具體的某一個namespace,直接ndctl destroy-namespace namespace1.0 --force
即可删除所有的namespaces,需要注意的是删除namespace 會清理掉目前namespace的所有資料。--all
4.3 指定類型 建立 namespaces
- 建立一個
類型的namespacefsdax
ndctl create-namespace --mode=fsdax --size=100G --region=region0 --force
指定在region0 上建立一個100G容量的 fsdax 模式namespace,建立成功則可以在
lsblk
指令下看到這個塊裝置
/dev/pmem0
。
除了以上參數,還可以指定一個比較重要的配置
--map=dev
或者
--map=mem
,儲存目前namespace 的中繼資料資訊,大概是每4k 需要64B的存儲。
dev
和
mem
分别制定的是将這部分中繼資料存放在pmem裝置上 或者 記憶體中。
- 上一條指令的基礎上 在
建立一個region0
模式的namespacedevdax
ndctl create-namespace --mode=devdax --size=100G --region=region0 --force
建立好之後能
ls -l /dev/dax1.0
看到這個裝置,它是一個字元裝置。
如果這一步失敗,可以根據這個 issue 嘗試解決:https://github.com/pmem/ndctl/issues/181
這樣建立出來的namespace 對應的 region 以及 dimm 關系圖如下:
4.4 變更已有namespace 類型
變更namespace1.0 的配置,從fsdax 模式變更為 devdax模式
ndctl create-namespace --mode=devdax --size=100G --reconfig=namespace1.0
。
注意:
reconfig 的流程會
- 先從已有的namespace中讀取 中繼資料資訊
- 然後删除已有的namespace,這一步會清理所有的資料
- 根據reconfig 的配置重新建立namespace
更多的建立資訊,可以參考https://pmem.io/ndctl/ndctl-create-namespace.html
5 namespace 的應用
這裡就很簡單了,主要是針對fsdax 裝置的使用
通過fsdax 模式建立出來的 一個塊裝置可以直接格式化成dax 支援的檔案系統 并挂載:
sudo mkfs.xfs -f /dev/pmem0
sudo mount -o dax /dev/pmem0 /mnt/pmem0
此時即可使用檔案接口進行讀寫。
6 fio測試 fsdax 和 devdax
建議測試的
fio
版本直接使用最新的
3.17
,這樣能夠使用比較新的ioengine (libpmem/dev-dax)
- 測試fsdax
以下綁定的numa 不一定準确,可以通過 lscpu
檢視numa的cpu,随便綁定一個,哪個性能好 則目前namespace 的region 就在哪個 numa上。
[global]
ioengine=libpmem #pmem引擎
direct=1
norandommap=1
randrepeat=0
runtime=60
time_based
size=1G
directory=./fio
group_reporting
[read256B-rand]
bs=256B
rw=randread
numjobs=32
iodepth=4
cpus_allowed=0-15,16-31 #綁定numa
-
檢視目前的 ndctl list --regions --namespaces
屬于哪一個region/dev/pmem0
-
檢視目前的region 屬于哪一個socket,0 則是numa node0, 1 則是numa node1等ipmctl show -region
- 測試devdax,不支援
開啟,直接通路的字元裝置direct
[global]
ioengine=dev-dax
direct=0
norandommap=1
randrepeat=0
runtime=60
time_based
size=1G
filename=/dev/dax1.0 #直接指定filename 為devdax模式的字元裝置即可
group_reporting
[read256B-rand]
bs=256B
rw=randread
numjobs=32
iodepth=4
cpus_allowed=0-15,16-31 #綁定numa
7 參考
- Introduction to Persistent Memory Configuration and Analysis Tools
- Persistent Memory Provisioning Introduction
- support virtual persistent memory
- https://pmem.io/ndctl/
- https://nvdimm.wiki.kernel.org/
- NDCTL Introduction
- PMEM 主機安裝環境詳解