linux下的单进程多线程的程序,要实现每个线程平均分配到多核cpu,主要有2个方法:

1:利用linux系统自己的线程切换机制,linux有一个服务叫做irqbalance,这个服务是linux系统自带的,默认会启动,这个服务的作用就是把多线程平均分配到CPU的每个核上面,只要这个服务不停止,多线程分配就可以自己实现。但是要注意,如果线程函数内部的有某个循环,且该循环内没有任何系统调用的话,可能会导致这个线程的CPU时间无法被切换出去。也就是占满CPU现象,此时加个系统调用,例如sleep,线程所占的CPU时间就可以切换出去了。

2:利用pthread库自带的线程亲和性设置函数,来设置线程在某个CPU核心上跑,这个需要在程序内部实现。同时注意不要和进程亲和性设置搞混淆了

 pthread_setaffinity_np函数,其原型定义如下:

#define _GNU_SOURCE             /* See feature_test_macros(7) */
#include <pthread.h>

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);

Compile and link with -pthread.

示例1程序如下,设置main线程固定在CPU核id为3。注意:需在linux下执行,windows下不支持的。

g++ setCPU_demo.cpp -o cpuDemo -lpthread

示例1: 

#include <iostream>
using namespace std;

int main(int argc, char *argv[])
{
    #if 1
	int your_fixed_cpu_kernl=3;
    cpu_set_t cpuset;
    CPU_ZERO(&cpuset);
    CPU_SET(your_fixed_cpu_kernl,&cpuset);
    int rc =pthread_setaffinity_np(pthread_self(),sizeof(cpu_set_t), &cpuset);
    if (rc != 0) {
      std::cerr << "Error calling pthread_setaffinity_np: " << rc << "\n";
    }
    #endif
    int count =1000000;
    while(count--)
    {
      cout<<"this is a test for main program:"<<count<<endl;
    }   
}

示例2:

当程序开启多个线程时候,封装指定CPU核的函数。

thread.join(), thread.detach()函数:

join的作用是让主线程等待直到该子线程执行结束。detach是用来和线程对象分离的,这样线程可以独立地执行,不过这样由于没有thread对象指向该线程而失去了对它的控制,当对象析构时线程会继续在后台执行,但是当主程序退出时并不能保证线程能执行完。如果没有良好的控制机制或者这种后台线程比较重要,最好不用detach而应该使用join。

#include <iostream>  
#include <thread>    
#include <unistd.h>

using namespace std;  


static void set_cpu(std::thread &thrd, int id)
{
    cpu_set_t cpuset;
    CPU_ZERO(&cpuset);
    CPU_SET(id,&cpuset);
    int rc =pthread_setaffinity_np(thrd.native_handle(),sizeof(cpu_set_t), &cpuset);
    if (rc != 0) {
      std::cerr << "Error calling pthread_setaffinity_np: " << rc << "\n";
    }
}
  
 
void thread01(int num)  
{  
    for (int i = 0; i < num; i++)  
    {  
        cout << "Thread 01 is working: "<< i << endl;  
        usleep(100);  
    }
   cout << "exit thread thread01" << endl;  
}  
void thread02(int num)  
{  
    for (int i = 0; i < num; i++)  
    {  
        cout << "Thread 02 is working: "<< i << endl;  
        usleep(200);  
    }  
    cout << "exit thread thread02" <<endl;
}  
  
int main()  
{  
    thread task01(thread01, 5);  
    thread task02(thread02, 5); 
    set_cpu(task01,2); //fixed run on CPU kernel 2
    set_cpu(task02,3); //fixed run on CPU kernel 3
    task01.join();
    task02.join(); 

    for(int i=0;i<5;i++) 
    {    
	cout<<"main program count: "<<i<<endl;
        usleep(200);  
    }
    cout<<"exit main thread"<<endl;  
      
}

示例3:

#define _GNU_SOURCE
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

#define handle_error_en(en, msg)

do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)

int main(int argc, char *argv[])
{
    int s, j;
    cpu_set_t cpuset;
    pthread_t thread;

    thread = pthread_self();

    /* Set affinity mask to include CPUs 0 to 7 */

    CPU_ZERO(&cpuset);
    for (j = 0; j < 8; j++)
        CPU_SET(j, &cpuset);

    s = pthread_setaffinity_np(thread, sizeof(cpu_set_t), &cpuset);
    if (s != 0)
        handle_error_en(s, "pthread_setaffinity_np");

    /* Check the actual affinity mask assigned to the thread */

    s = pthread_getaffinity_np(thread, sizeof(cpu_set_t), &cpuset);
    if (s != 0)
        handle_error_en(s, "pthread_getaffinity_np");

    printf("Set returned by pthread_getaffinity_np() contained:\n");
    for (j = 0; j < CPU_SETSIZE; j++)
        if (CPU_ISSET(j, &cpuset))
            printf("    CPU %d\n", j);

    exit(EXIT_SUCCESS);
}

参考:

https://www.cnblogs.com/x_wukong/p/5924298.html

https://blog.csdn.net/guotianqing/article/details/80958281

https://www.cnblogs.com/whlook/p/6573659.html(C++ thread)

Logo

更多推荐