HACK #11cpuset
本節介紹控制物理CPU分配的cpuset。
cpuset是Linux控制組(Cgroup)之一,其功能是指定特定進程或線程所使用的CPU組。另外,除CPU以外,同樣還能指定內存節點的分配。
以前的內核具有CPU affinity功能,該功能將線程分配給特定CPU。現在的內核中雖然也有affinity(taskset命令),但推薦使用cpuset。
用法
使用cpuset前,必須通過內核config啟用cpuset功能。
CONFIG_CPUSETS=y
最近的發布版在標准中就已啟用。cpuset就是作為Cgroup提供的一個功能。因此,使用cpuset時,就需要掛載 Cgroup文件系統。使用下列方法啟用cpuset選項,掛載Cgroup后,就可以使用cpuset(參考Hack #7)。
# mount -o cpuset -t cgroup cgroup /cgroup
在這里創建一個新的CPU分配組GroupA。與其他Cgroup同樣在掛載的Cgroup下創建新目錄GroupA,作為分組GroupA。
# mkdir /cgroup/GroupA
編輯新創建分組GroupA的cpuset,修改CPU分配情況。這里以僅將CPU0分配給分組GroupA的情況為例進行說明。在分組GroupA下的特殊文件cpuset.cpus內寫入要分配的CPU編號,使用下列命令,來控制分組的cpuset。
# echo 0 > /cgroup/GroupA/cpuset.cpus
到這一步,就完成了僅使用CPU0作為GroupA的CPU分配的設置。
接下來,在這個分組GroupA中添加進程。這里將當前shell添加到GroupA中。使用下列命令,將PID(
$$ 表示shell本身的PID)寫入GroupA下的task文件。
# echo
$$
> /cgroup/GroupA/task
此后由當前shell啟動的進程全部在這個GroupA下,使用的CPU僅限於0號CPU。
現在確認所使用的CPU數量是否受限,以及產生的效果如何。本節顯示的是以Fedora 12為例的情況。
本示例中使用的Fedora 12內核如下。
# uname -a
Linux fedora12 2.6.31.12-174.2.22.fc12.x86_64 #1 SMP Fri Feb 19 18:55:03 UTC 2010 x86_64 x86_64 x86_64 GNU/Linux
如果使用cpuset改變所使用的CPU數量會怎么樣?比較內核的編譯時間。
首先准備好要進行比較的編譯。為了避免磁盤性能的影響,首先創建內存文件系統tmpfs,並在其中配置源文件。創建目錄/tmp/build,掛載 tmpfs,命令如下所示。
# mkdir /tmp/build
# mount -t tmpfs none /tmp/build
本次測量的是內核源代碼每次在創建的tmpfs下解壓縮tarball時,使用默認config所花費的內核編譯時間。使用的一系列命令行如下。
# cd /tmp/build/
# tar jxf /ext4data/kernel/linux-2.6.33.tar.bz2 # cd linux-2.6.33/ # make defconfig # time make -j 2
首先測量Linux 2.6.33的編譯時間。
將Cgroup掛載到/cgroup,創建分組GroupA。
# mount -o cpuset -t cgroup cgroup /cgroup
# mkdir /cgroup/GroupA
接下來看一下向分組GroupA分配兩個CPU時的結果。
# echo"0-1" > /cgroup/GroupA/cpuset.cpus # echo 0 > /cgroup/GroupA/cpuset.mems mems默認為空,因此需要填入值 # echo $$ > /cgroup/GroupA/tasks
編譯時間如下。
# time make -j 2 real 4m55.568s user 2m42.066s sys 5m4.575s
然后將CPU縮減到只有0號CPU。
# echo 0 > /cgroup/GroupA/cpuset.cpus # echo 0 > /cgroup/GroupA/cpuset.mems # echo $$ > /cgroup/GroupA/tasks # mount -t tmpfs none /tmp/build # cd /tmp/build/ # tar jxf /ext4data/kernel/linux-2.6.33.tar.bz2 # cd linux-2.6.33/ # make defconfig # time make -j 2 real 7m44.491s user 2m47.319s sys 4m56.737s
可以看到,CPU數量變為1,實際花費的時間(real)增加。
下面以對虛擬化(KVM)進程所使用的CPU進行限制的情況為例,看一下將分配給KVM進程的CPU固定,並確保主機操作系統能夠一直使用CPU后,是否能夠減少虛擬化的影響。
這個示例同樣使用Fedora 12。
首先使用KVM,啟動兩個客戶端操作系統。然后,在客戶端操作系統中循環進行內核編譯,加大CPU負載。
在解壓縮Linux 2.6.33源代碼的目錄下,無限循環執行make clean和make命令,增加客戶端操作系統的CPU負載。
hshimamoto@ubuntu:~/kernel/linux-2.6.33$ while :; do make clean; time make; done hshimamoto@opensuse:~/kernel/linux-2.6.33> while :; do make clean; time make; done
在這種情況下計算主機操作系統上的內核編譯時間。同前例一樣,需要創建tmpfs,消除磁盤性能的影響后再進行測量。計算結果如下。
# time make -j 2 real 8m20.468s user 2m45.890s sys 4m51.091s
然后,將KVM的qemu-kvm進程可以使用的CPU設置為只有0號CPU。
# mount -o cpuset -t cgroup cgroup /cgroup
# mkdir /cgroup/kvm
# echo 0 > /cgroup/kvm/cpuset.meme 將kvm分組的cpuset設為只有0 # echo 0 > /cgroup/kvm/cpuset.cpus
將啟動中的qemu-kvm移動到kvm分組。
# ps x | grep qemu
2495 pts/2 Sl+ 238:37 qemu-kvm 2628 pts/3 Sl+ 255:33 qemu-kvm # for i in '\ls /proc/2495/task/'; do echo $i > /cgroup/kvm/tasks; done # for i in '\ls /proc/2628/task/'; do echo $i > /cgroup/kvm/tasks; done
另外,ksmd(參考Hack #36)也使用CPU,因此這里也將其加入kvm分組。
# ps ux | grep ksmd
root 35 2.2 0.0 0 0? SN Mar23 119:42[ksmd] # echo 35 > /cgroup/kvm/tasks
現在,主機操作系統的內核編譯時間就變成如下所示。
# time make -j 2 real 7m55.081s user 2m43.303s sys 5m12.039s
可以發現,內核編譯所花費的實際時間減少了接近30秒。
這是因為虛擬化的KVM進程只在CPU0上運行,在主機操作系統上就可以使用100%的CPU。
小結
本節介紹了使用Linux中的Cgroup的cpuset。通過使用這個功能,就可以限制特定進程所使用的CPU。從另一個角度來看,通過固定使用的CPU,還可以提高緩存的利用效率和性能。
—Hiroshi Shimamoto
