我编写了一个小程序,在Callgrind对它进行动态检测之前,它的运行情况非常好:
$ g++ -std=c++11 -pthread -g -ggdb -o program.exe program.cpp
$ time valgrind --tool=callgrind ./program.exe
代码:
#include <atomic>
#include <thread>
#include <iostream>
constexpr int CST_TARGET = 10*1000;
std::atomic<bool> g_lock = {false};
std::atomic<bool> g_got_work = {true};
int g_passer = 0;
long long g_total = 0;
void producer() {
while (1) {
while (g_lock.load(std::memory_order_seq_cst));
if (g_passer >= CST_TARGET) {
g_got_work.store(false, std::memory_order_seq_cst);
return;
}
++g_passer;
g_lock.store(true, std::memory_order_seq_cst);
}
}
void consumer() {
while (g_got_work.load(std::memory_order_seq_cst)) {
if (g_lock.load(std::memory_order_seq_cst)) {
g_total += g_passer;
g_lock.store(false, std::memory_order_seq_cst);
}
}
}
int main() {
std::atomic<int> val(0);
std::thread t1(producer);
std::thread t2(consumer);
t1.join();
t2.join();
std::cout << "g_passer = " << g_passer << std::endl;
std::cout << "g_total = " << g_total << std::endl;
return 0;
}
仪器不会在10分钟后结束,所以我终止了它,并查看了KCachegrind的统计信息。
std::atomic<bool>::load(...)
的调用数亿至数十亿。有什么想法可以使Callgrind的哪些部分改变原子调用的行为并使它们失败?程序本身在没有Callgrind的情况下以毫秒为单位运行。
最佳答案
使用--fair-sched = yes应该可以解决问题。