NanoPi2具有4个CPU核心。
当运行一个程序时,想让它运行在特定的CPU核心上。
那就要改变CPU亲和性(affinity)了。 那么什么是CPU亲和性呢,以及更改的原因可以看这里。
线程亲和性的设置和获取主要通过下面两个函数来实现:
- 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); //初始化,设为空
- 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_set_t的定义 如下:
- # define __CPU_SETSIZE 1024
- # define __NCPUBITS (8 * sizeof (__cpu_mask))
- typedef unsigned long int __cpu_mask;
- # define __CPUELT(cpu) ((cpu) / __NCPUBITS)
- # define __CPUMASK(cpu) ((__cpu_mask) 1 << ((cpu) % __NCPUBITS))
- typedef struct
- {
- __cpu_mask __bits[__CPU_SETSIZE / __NCPUBITS];
- } cpu_set_t;
-
- # define __CPU_ZERO(cpusetp)
- do {
- unsigned int __i;
- cpu_set_t *__arr = (cpusetp);
- for (__i = 0; __i < sizeof (cpu_set_t) / sizeof (__cpu_mask); ++__i)
- __arr->__bits[__i] = 0;
- } while (0)
- # define __CPU_SET(cpu, cpusetp)
- ((cpusetp)->__bits[__CPUELT (cpu)] |= __CPUMASK (cpu))
- # define __CPU_CLR(cpu, cpusetp)
- ((cpusetp)->__bits[__CPUELT (cpu)] &= ~__CPUMASK (cpu))
- # define __CPU_ISSET(cpu, cpusetp)
- (((cpusetp)->__bits[__CPUELT (cpu)] & __CPUMASK (cpu)) != 0)
复制代码
新建C文件
#vim aaa.c 程序如下:
- #define _GNU_SOURCE
- #define _USE_GNU
- #include
- #include
- #include
- #include
- #include
- #include
-
- void *nanopifunction(void *arg)
- {
- cpu_set_t mask;
- cpu_set_t get;
- char buf[256];
- int i;
- int j;
- int num = sysconf(_SC_NPROCESSORS_CONF);//获取CPU核心数
- 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 failedn");
- }
- CPU_ZERO(&get);
- if (pthread_getaffinity_np(pthread_self(), sizeof(get), &get) < 0) {
- fprintf(stderr, "get thread affinity failedn");
- }
- for (j = 0; j < num; j++) {
- if (CPU_ISSET(j, &get)) {
- printf("thread %d is running in processor %dn", (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 *)nanopifunction, NULL) != 0) {//新建线程
- fprintf(stderr, "create thread failed!n");
- return -1;
- }
- pthread_join(tid, NULL);// 等待线程的结束
- return 0;
- }
复制代码
其中:
pthread_self():获得线程自身的ID
编译程序: # gcc aaa.c -lpthread
# ./a.out
这段代码将使nanopifunction线程在所有cpu核心中依次执行一段时间,在NanoPi2上的执行结果为 :
可以看到线程1994568800分别在四个CPU核心上运行了一段时间。在一些嵌入式设备中,运行的进程线程比较单一,如果指定进程线程运行于特定的cpu核,减少进程、线程的核间切换,有可能可以获得更高的性能。
|