我试图理解Linux的perf
,但发现了一些非常令人困惑的行为:
我编写了一个简单的多线程示例,其中一个线程针对每个核心进行绑定;每个线程在本地运行计算,并且彼此不通信(请参见下面的test.cc
)。我认为这个示例应该有非常低的上下文切换甚至为零。然而,使用Linux的perf
来分析示例时显示了数千次上下文切换-比我预期的要多得多。我进一步使用Linux命令sleep 20
进行比较,显示更少的上下文切换。
对于这个分析结果,我感到非常困惑。是什么导致了如此多的上下文切换?
> sudo perf stat -e sched:sched_switch ./test
Performance counter stats for './test':
6,725 sched:sched_switch
20.835 seconds time elapsed
> sudo perf stat -e sched:sched_switch sleep 20
Performance counter stats for 'sleep 20':
1 sched:sched_switch
20.001 seconds time elapsed
为了复现结果,请运行以下代码:
perf stat -e context-switches sleep 20
perf stat -e context-switches ./test
要编译源代码,请输入以下代码:
g++ -std=c++11 -pthread -o test test.cc
// test.cc
#include <iostream>
#include <thread>
#include <vector>
int main(int argc, const char** argv) {
unsigned num_cpus = std::thread::hardware_concurrency();
std::cout << "Launching " << num_cpus << " threads\n";
std::vector<std::thread> threads(num_cpus);
for (unsigned i = 0; i < num_cpus; ++i) {
threads[i] = std::thread([i] {
int j = 0;
while (j++ < 100) {
int tmp = 0;
while (tmp++ < 110000000) { }
}
});
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
CPU_SET(i, &cpuset);
int rc = pthread_setaffinity_np(threads[i].native_handle(),
sizeof(cpu_set_t), &cpuset);
if (rc != 0) {
std::cerr << "Error calling pthread_setaffinity_np: " << rc << "\n";
}
}
for (auto& t : threads) {
t.join();
}
return 0;
}
top
命令,查看是否有其他并行运行的程序占用了 CPU,例如网络浏览器。并行任务可能会导致所有这些上下文切换。 - Michael Veksler