3,880
社区成员




cpu_set_t mask;
int blist[8]={2, 5, 13, 9, 3, 6, 7, 4}; //设置需要绑定的核列表
#pragma omp parallel private(mask)
{
CPU_ZERO(&mask);
CPU_SET(blist[omp_get_thread_num()], &mask); //omp_get_thread_num()获取的估计是omp自己给定的序号,按序号获取要绑定的cpu号,然后填充mask。
sched_setaffinity(0,sizeof(cpu_set_t), &mask); //这个函数是进程(不是线程)绑定到CPU核,0代表当前进程,所以要在过程内部运行
}
大致说明其实openmp是把任务按cpu的数量复制成几个进程来处理,总体感觉openmp是一个对本身可以并行且无需更多设置的任务(比如简单的累加)处理比较简易,但真的是太过简单,处理复杂一点的问题估计很够呛。#include <stdio.h>
#include <unistd.h>
#include <stdint.h>
#include <malloc.h>
/* 以下三行先后次序不能错,否则CPU_ZERO等宏有问题 */
#define __USE_GNU
#include <sched.h>
#include <pthread.h>
/* 以下可以写在函数里,如果有很多线程管理最好设置为全局量,在软件启动时赋值,减少时间消耗*/
int cpu_num; //cpu核(含超线程,例如Xeon E5-2620 6核12线程)
size_t mask_size; //cpu_set_t类型长度
cpu_set_t *mask; //用来setaffinity的掩码
/*自定义函数,设置线程号与核号的绑定,核号是0~(cpu_num - 1);可以直接在线程函数里运行,也可以在专门的线程管理程序里干这事儿,主要函数就是pthread_setaffinity_np() ,成功返回 0*/
int mythread_setaffinity(int core_id, pthread_t tid)
{
CPU_ZERO(mask);
CPU_SET(core_id,mask);
if (core_id > (cpu_num - 1) || core_id < 0) return 1;
return pthread_setaffinity_np(tid ,mask_size, mask);
}
void *mythread_process1(void *args)
{
int core_id = cpu_num - 1;
if(mythread_setaffinity(core_id, pthread_self()) != 0){
fprintf(stderr, "thread %lu set affinity core id %d failed.\n", pthread_self(), core_id);
}
//... ...
pthread_exit(NULL);
}
void *mythread_process2(void *args)
{
//... ...
pthread_exit(NULL);
}
int main(int argc, char **argv)
{
cpu_num = sysconf(_SC_NPROCESSORS_ONLN);
mask_size = sizeof(cpu_set_t);
mask = (cpu_set_t *)malloc(mask_size);
pthread_t tid1, tid2;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
void *args1 = NULL, *args2 = NULL;
pthread_create(&tid1, &attr, mythread_process1, args1);
pthread_create(&tid2, NULL, mythread_process2, args2);
mythread_setaffinity(cpu_num - 2, tid2);
//pthread_detach(tid2);
pthread_join(tid2, NULL);
pause();
return 0;
}
如果需要实时多任务处理,设置CPU与线程的绑定是必要的。操作系统线程调度本身就很消耗时间,而且它还经常调来调去。