最近在對項目進行性能優化,由於在多核平台上,所以了解了些進程、線程綁定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);
從函數名以及參數名都很明了,唯一需要點解釋下的可能就是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);
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;
}
這段代碼將使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
在一些嵌入式設備中,運行的進程線程比較單一,如果指定進程線程運行於特定的cpu核,減少進程、線程的核間切換,有可能可以獲得更高的性能。
http://www.ibm.com/developerworks/cn/linux/l-affinity.html