Linux编程之《进程/线程绑定CPU》
Intro
-----
通常我们在编写服务器代码时,可以通过将当前进程绑定到固定的CPU核心或者线程绑定到固定的CPU核心来提高系统调度程序的效率来提高程序执行的效率,下面将完整代码贴上。
1 /************************************************ 2 * 该例程讲解了进程、线程绑定到固定的cpu核心上运行 3 * 来提高程序运行效率 4 ************************************************/ 5 #include <unistd.h> 6 #ifndef __USE_GNU 7 #define __USE_GNU // 为了使用SET_SET()等宏定义,但unistd.h里面好像已经定义了 8 #endif 9 #include <sched.h> 10 #include <pthread.h> 11 #include <stdio.h> 12 #include <vector> 13 14 unsigned int systemCPUNum() 15 { 16 // _SC_NPROCESSORS_CONF的值为CPU个数,基于0开始编号 17 return sysconf(_SC_NPROCESSORS_CONF); 18 } 19 20 bool currentProcessAffinity(std::vector<unsigned int>& runningCPUVector) 21 { 22 cpu_set_t cpuSet; 23 24 // 清空一个CPU集合 25 CPU_ZERO(&cpuSet); 26 27 // 得到指定进程ID绑定到哪个CPU 28 int ret = sched_getaffinity(0, // 0代表当前进程 29 sizeof(cpuSet), 30 &cpuSet); 31 if (ret < 0) 32 { 33 return false; 34 } 35 36 unsigned int cpuNum = systemCPUNum(); 37 runningCPUVector.clear(); 38 for (unsigned int i = 0; i < cpuNum; ++i) 39 { 40 // 检查一个CPU号是否在一个集合中 41 if (CPU_ISSET(i, &cpuSet)) 42 { 43 runningCPUVector.push_back(i); 44 } 45 } 46 47 return true; 48 } 49 50 bool setCurrentProcessAffinity(const std::vector<unsigned int>& needBindCPUVector) 51 { 52 cpu_set_t cpuSet; 53 54 // 清空一个CPU集合 55 CPU_ZERO(&cpuSet); 56 57 for (auto& iter : needBindCPUVector) 58 { 59 CPU_SET(iter, &cpuSet); 60 } 61 62 // 将指定进程ID绑定到CPU 63 int ret = sched_setaffinity(0, // 0代表当前进程 64 sizeof(cpuSet), 65 &cpuSet); 66 if (ret < 0) 67 { 68 return false; 69 } 70 71 return true; 72 } 73 74 bool currentThreadAffinity(std::vector<unsigned int>& runningCPUVector) 75 { 76 cpu_set_t cpuSet; 77 78 // 清空一个CPU集合 79 CPU_ZERO(&cpuSet); 80 81 // 得到指定线程ID绑定到哪个CPU 82 int ret = pthread_getaffinity_np(pthread_self(), 83 sizeof(cpuSet), 84 &cpuSet); 85 if (ret < 0) 86 { 87 return false; 88 } 89 90 unsigned int cpuNum = systemCPUNum(); 91 runningCPUVector.clear(); 92 for (unsigned int i = 0; i < cpuNum; ++i) 93 { 94 // 检查一个CPU号是否在一个集合中 95 if (CPU_ISSET(i, &cpuSet)) 96 { 97 runningCPUVector.push_back(i); 98 } 99 } 100 101 return true; 102 } 103 104 bool setCurrentThreadAffinity(const std::vector<unsigned int>& needBindCPUVector) 105 { 106 cpu_set_t cpuSet; 107 108 // 清空一个CPU集合 109 CPU_ZERO(&cpuSet); 110 111 for (auto& iter : needBindCPUVector) 112 { 113 CPU_SET(iter, &cpuSet); 114 } 115 116 // 将指定线程ID绑定到CPU 117 int ret = pthread_setaffinity_np(pthread_self(), 118 sizeof(cpuSet), 119 &cpuSet); 120 if (ret < 0) 121 { 122 return false; 123 } 124 125 return true; 126 } 127 128 int main() 129 { 130 printf("*****Process bind CPU sample*****\n"); 131 unsigned int cpuNum = systemCPUNum(); 132 printf("Current system has %u CPU(s)\n", cpuNum); 133 134 std::vector<unsigned int> runningCPUVector; 135 if (!currentProcessAffinity(runningCPUVector)) 136 { 137 printf("Get current process was bound witch CPU failed\n"); 138 return 1; 139 } 140 141 for (auto& iter : runningCPUVector) 142 { 143 printf("Current process is running at %u CPU\n", iter); 144 } 145 146 std::vector<unsigned int> needBindCPUVector {0, 2}; 147 if (!setCurrentProcessAffinity(needBindCPUVector)) 148 { 149 printf("Current process bind CPU failed\n"); 150 return 1; 151 } 152 153 printf("Current process bind CPU success\n"); 154 155 runningCPUVector.clear(); 156 if (!currentProcessAffinity(runningCPUVector)) 157 { 158 printf("Get current process was bound witch CPU failed\n"); 159 return 1; 160 } 161 162 for (auto& iter : runningCPUVector) 163 { 164 printf("Current process is running at %u CPU\n", iter); 165 } 166 167 printf("\n*****Thread bind CPU sample*****\n"); 168 runningCPUVector.clear(); 169 if (!currentThreadAffinity(runningCPUVector)) 170 { 171 printf("Get current thread was bound witch CPU failed\n"); 172 return 1; 173 } 174 175 for (auto& iter : runningCPUVector) 176 { 177 printf("Thread %lu is running at %u CPU\n", pthread_self(), iter); 178 } 179 180 needBindCPUVector.clear(); 181 needBindCPUVector.push_back(1); 182 if (!setCurrentThreadAffinity(needBindCPUVector)) 183 { 184 printf("Current thread bind CPU failed\n"); 185 return 1; 186 } 187 188 printf("Thread %lu bind CPU success\n", pthread_self()); 189 190 runningCPUVector.clear(); 191 if (!currentThreadAffinity(runningCPUVector)) 192 { 193 printf("Get current thread was bound witch CPU failed\n"); 194 return 1; 195 } 196 197 for (auto& iter : runningCPUVector) 198 { 199 printf("Thread %lu is running at %u CPU\n", pthread_self(), iter); 200 } 201 202 return 0; 203 }
程序执行的输出结果:
*****Process bind CPU sample*****
Current system has 4 CPU(s)
Current process is running at 0 CPU
Current process is running at 1 CPU
Current process is running at 2 CPU
Current process is running at 3 CPU
Current process bind CPU success
Current process is running at 0 CPU
Current process is running at 2 CPU
*****Thread bind CPU sample*****
Thread 139871129114432 is running at 0 CPU
Thread 139871129114432 is running at 2 CPU
Thread 139871129114432 bind CPU success
Thread 139871129114432 is running at 1 CPU
该例子的github地址:https://github.com/chxuan/samples/blob/master/BindCPU/BindCPU.cpp
兴趣是最好的老师,我的github地址:https://github.com/chxuan