绑定CPU逻辑核心的利器——taskset
? ? ? ? 在工作中,我們可能遇到這樣的需求:如何評估程序在一核和多核下的工作效率差距?最簡單的想法是找一臺只有一個CPU邏輯核的機器和一臺有多個邏輯核的機器。(轉載請指明出于breaksoftware的csdn博客)但是這種方式有明顯的問題:
- 不容易找到這樣的機器。
- 找到的機器不能保證其他配置一致,比如CPU主頻。
- 找的的機器不能保證環境一致,比如操作系統或者運行中的其他程序。
? ? ? ? 于是比較好的方式是:在一臺多邏輯核的機器上指定程序可以運行在哪些核上。為了可以證明我們程序在多個核心上切換,我編寫了如下代碼
// build script:gcc -lpthread bind_core.c -o bind_core
#include <stdio.h>
#include <pthread.h>
#include <sched.h>void* thread_routine(void* arg) {int cpu = -1;while(1) {int cur_cpu = sched_getcpu();if (cur_cpu != cpu) {printf("pre:%d, cur:%d\n", cpu, cur_cpu);cpu = cur_cpu;}}
};void test_cpu_switch() {pthread_t thread;pthread_create(&thread, NULL, thread_routine, NULL);pthread_detach(thread);sleep(100);
}
? ? ? ? 這段代碼中啟動了一個線程,通過sched_getcpu函數不停檢測當前占用的邏輯核心編號。如果發生核心切換,就打印出來。在一臺相對繁忙的40個邏輯核心機器上,其輸出結果如下:
? ? ? ? 上圖可以看出,程序分別在:0,1,2,3,7,8,10,12,13,14,15,17,19,21號邏輯核上運行過。為了讓CPU在固定的核心上執行,我們可以使用taskset指令,讓程序綁定邏輯核心。
taskset -c 0,10 ./bind_core
? ? ? ? 上面指令讓bind_core執行于0和10號邏輯核心上,這樣我就可以看到它在這兩個核心上的切換
? ? ? ? 基于上面的基礎,我們可以編寫測試代碼,看看多線程程序在單核心和多核心下的處理能力
#include <stdio.h>
#include <pthread.h>
#include <sched.h>unsigned long g_a = 0;
unsigned long g_b = 0;void* thread_routine(void* arg) {while(1) {(*((unsigned long*)arg))++;}
};void test_cpu_ability() {pthread_t thread_a;pthread_create(&thread_a, NULL, thread_routine, &g_a);pthread_detach(thread_a);pthread_t thread_b;pthread_create(&thread_b, NULL, thread_routine, &g_b);pthread_detach(thread_b);sleep(3);printf("a:%lu\tb:%lu\n", g_a, g_b);
};
? ? ? ? 這段代碼啟動了兩個線程,每個線程分別不停自增。過了3秒后,通過兩個全局變量的值表達出不同場景的處理能力:
- 不設置CPU綁定
./bind_core a:999409723 b:994174648 - 設置綁定到0號CPU邏輯核心
taskset -c 0 ./bind_core a:563819215 b:564766868 - 設置綁定到0,1號CPU邏輯核心
taskset -c 0,1 ./bind_core a:1113333145 b:1072107088 - 設置綁定到0,1,2號CPU邏輯核心
taskset -c 0,1,2 ./bind_core a:1114825104 b:1113289961
? ? ? ? 可以看到,當啟動兩個線程時,綁定一個核心的處理能力是綁定兩個核心的處理能力的一半左右。而綁定的核心數超過線程數時(如綁定到0,1,2號邏輯核心),其效率并沒有明顯提高。當然上述結論有個前提:這是CPU資源密集型的場景。
?
總結
以上是生活随笔為你收集整理的绑定CPU逻辑核心的利器——taskset的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C++拾趣——C++11的语法糖auto
- 下一篇: zookeeper快速入门——简介