linux 提供CPU排程函數,可以将CPU某一個核和指定的線程綁定到一塊運作。
這樣能夠充分利用CPU,且減少了不同CPU核之間的切換,尤其是在IO密集型壓力之下能夠提供較為友好的性能。
通過
sched_setaffinity
設定 CPU 親和力的掩碼,進而将該線程或者程序和指定的CPU綁定
一個CPU的親合力掩碼用一個
cpu_set_t
結構體來表示一個CPU集合,下面的幾個宏分别對這個掩碼集進行操作:
CPU_ZERO()
清空一個集合
CPU_SET()
與
CPU_CLR()
分别對将一個給定的CPU号加到一個集合或者從一個集合中去掉.
CPU_ISSET()
檢查一個CPU号是否在這個集合中
- 頭檔案
sched.h
-
該函數設定程序為pid的這個程序,讓它運作在mask所設定的CPU上.sched_setaffinity(pid_t pid, unsigned int cpusetsize, cpu_set_t *mask)
- 如果pid的值為0,則表示指定的是目前程序,使目前程序運作在mask所設定的那些CPU上.
- 第二個參數cpusetsize是mask所指定的數的長度.通常設定為sizeof(cpu_set_t).如果目前pid所指定的程序此時沒有運作在mask所指定的任意一個CPU上,則該指定的程序會從其它CPU上遷移到mask的指定的一個CPU上運作.
- mask 即使用者 通過
接口,線程ID 綁定刀片集合中的一個CPU上,使用mask來表示cpu集合中的CPUCPU_SET
-
sched_getaffinity(pid_t pid, unsigned int cpusetsize, cpu_set_t *mask)
該函數獲得pid所訓示的程序的CPU位掩碼,并将該掩碼傳回到mask所指向的結構中.即獲得指定pid目前可以運作在哪些CPU上.同樣,如果pid的值為0.也表示的是目前程序
使用方式如下:
#include <stdio.h>
#include <unistd.h>
#include <time.h>
#include <signal.h>
#include <string.h>
#define __USE_GNU
#include <sched.h>
#include <pthread.h>
int num;
void *thread_func1(void *arg) {
cpu_set_t mask; //CPU核的集合
cpu_set_t get; //擷取在集合中的CPU
int *a = (int*)arg;
printf("the a is:%d\n",*a); //顯示是第幾個線程
CPU_ZERO(&mask); //置空
CPU_SET(*a,&mask); // 将目前線程和CPU綁定
if(sched_setaffinity(0, sizeof(mask), &mask)) {
printf("warning ! set affinity failed! \n");
} else {
while (1)
{
CPU_ZERO(&get);
if (sched_getaffinity(0, sizeof(get), &get) == -1)//擷取線程CPU親和力
{
printf("warning: cound not get thread affinity, continuing...\n");
}
int i;
for (i = 0; i < num; i++)
{
if (CPU_ISSET(i, &get))//判斷線程與哪個CPU有親和力
{
printf("this thread %d is running processor : %d\n", i,i);
}
}
}
}
return NULL;
}
void *thread_func2(void *arg) {
cpu_set_t mask; //CPU核的集合
cpu_set_t get; //擷取在集合中的CPU
int *a = (int*)arg;
printf("the a is:%d\n",*a); //顯示是第幾個線程
CPU_ZERO(&mask); //置空
CPU_SET(*a,&mask); // 将目前線程和CPU綁定
if(sched_setaffinity(0, sizeof(mask), &mask) == -1) {
printf("warning ! set affinity failed! \n");
} else {
while (1)
{
CPU_ZERO(&get);
if (sched_getaffinity(0, sizeof(get), &get) == -1)//擷取線程CPU親和力
{
printf("warning: cound not get thread affinity, continuing...\n");
}
int i;
for (i = 0; i < num; i++)
{
if (CPU_ISSET(i, &get))//判斷線程與哪個CPU有親和力
{
printf("this thread %d is running processor : %d\n", i,i);
}
}
}
}
return NULL;
}
int main() {
pthread_t t1;
pthread_t t2;
int t_1 = 0;
int t_2 = 1;
// 擷取CPU核數
num = sysconf(_SC_NPROCESSORS_CONF);
// 需要傳入t_1,t_2,來作為線程的參數,用來核CPU核綁定
pthread_create(&t1, NULL, (void *)thread_func1,&t_1);
pthread_create(&t2, NULL, (void *)thread_func2,&t_2);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
printf("main thread end\n");
return 0;
}
如果使用到pthread,則需要将
pthread.h
放到
sched.h
之後,并在
sched.h
之前聲明
#define __USE_GNU
,
否則會出現
undefined reference CPU_ZERO
等錯誤
編譯:
gcc sched_cpu.c -o sched_cpu -pthread
以上代碼将兩個線程分别綁定到0,1号CPU上