執行緒與cpu進行繫結——006非常全面
阿新 • • 發佈:2019-02-04
http://blog.csdn.net/jxnu_xiaobing/article/details/44955613
最近在對專案進行效能優化,由於在多核平臺上,所以瞭解了些程序、執行緒繫結cpu核的問題,在這裡將所學記錄一下。
不管是執行緒還是程序,都是通過設定親和性(affinity)來達到目的。對於程序的情況,一般是使用sched_setaffinity這個函式來實現,網上講的也比較多,這裡主要講一下執行緒的情況。
與程序的情況相似,執行緒親和性的設定和獲取主要通過下面兩個函式來實現:
int pthread_setaffinity_np(pthread_t thread, size_t cpusetsize,
const cpu_set_t *cpuset );
int pthread_getaffinity_np(pthread_t thread, size_t cpusetsize,
cpu_set_t *cpuset);
- 1
- 2
- 3
- 4
從函式名以及引數名都很明瞭,唯一需要點解釋下的可能就是cpu_set_t這個結構體了。這個結構體的理解類似於select中的fd_set,可以理解為cpu集,也是通過約定好的巨集來進行清除、設定以及判斷:
//初始化,設為空
void CPU_ZERO (cpu_set_t *set);
//將某個cpu加入cpu集中
void CPU_SET (int cpu, cpu_set_t *set );
//將某個cpu從cpu集中移出
void CPU_CLR (int cpu, cpu_set_t *set);
//判斷某個cpu是否已在cpu集中設定了
int CPU_ISSET (int cpu, const cpu_set_t *set);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
cpu集可以認為是一個掩碼,每個設定的位都對應一個可以合法排程的 cpu,而未設定的位則對應一個不可排程的 CPU。換而言之,執行緒都被綁定了,只能在那些對應位被設定了的處理器上執行。通常,掩碼中的所有位都被置位了,也就是可以在所有的cpu中排程。 以下為測試程式碼:
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <sched.h>
void *myfun(void *arg)
{
cpu_set_t mask;
cpu_set_t get;
char buf[256];
int i;
int j;
int num = sysconf(_SC_NPROCESSORS_CONF);
printf("system has %d processor(s)\n", num);
for (i = 0; i < num; i++) {
CPU_ZERO(&mask);
CPU_SET(i, &mask);
if (pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask) < 0) {
fprintf(stderr, "set thread affinity failed\n");
}
CPU_ZERO(&get);
if (pthread_getaffinity_np(pthread_self(), sizeof(get), &get) < 0) {
fprintf(stderr, "get thread affinity failed\n");
}
for (j = 0; j < num; j++) {
if (CPU_ISSET(j, &get)) {
printf("thread %d is running in processor %d\n", (int)pthread_self(), j);
}
}
j = 0;
while (j++ < 100000000) {
memset(buf, 0, sizeof(buf));
}
}
pthread_exit(NULL);
}
int main(int argc, char *argv[])
{
pthread_t tid;
if (pthread_create(&tid, NULL, (void *)myfun, NULL) != 0) {
fprintf(stderr, "thread create failed\n");
return -1;
}
pthread_join(tid, NULL);
return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
gcc test.c -o test -lpthread
- 1
這段程式碼將使myfun執行緒在所有cpu中依次執行一段時間,在我的四核cpu上,執行結果為 :
system has 4 processor(s)
thread 1095604544 is running in processor 0
thread 1095604544 is running in processor 1
thread 1095604544 is running in processor 2
thread 1095604544 is running in processor 3
- 1
- 2
- 3
- 4
- 5
在一些嵌入式裝置中,執行的程序執行緒比較單一,如果指定程序執行緒運行於特定的cpu核,減少程序、執行緒的核間切換,有可能可以獲得更高的效能。