C++;线程:共享内存不更新,尽管没有竞争 我正在试用C++标准线程。我编写了一个小的基准测试来测试性能开销和总体吞吐量。其原理是在一个或多个线程中运行一个10亿次迭代的循环,不时进行小的暂停
在第一个版本中,我使用共享内存中的计数器(即普通变量)。我列举了以下输出: 不幸的是,显示屏上显示了一些计数器,好像它们未初始化一样 我可以通过将每个计数器的结束值存储在C++;线程:共享内存不更新,尽管没有竞争 我正在试用C++标准线程。我编写了一个小的基准测试来测试性能开销和总体吞吐量。其原理是在一个或多个线程中运行一个10亿次迭代的循环,不时进行小的暂停,c++,multithreading,c++11,benchmarking,stdthread,C++,Multithreading,C++11,Benchmarking,Stdthread,在第一个版本中,我使用共享内存中的计数器(即普通变量)。我列举了以下输出: 不幸的是,显示屏上显示了一些计数器,好像它们未初始化一样 我可以通过将每个计数器的结束值存储在原子中以供以后显示来解决这个问题。但是我不理解为什么基于简单共享内存的版本不能正常工作:每个线程使用自己的计数器,因此没有竞速条件。即使显示线程也仅在计数线程完成后访问计数器。使用volatile也没有帮助 有谁能解释我这种奇怪的行为(好像记忆没有更新)并告诉我是否遗漏了什么 以下是共享变量: const int maxthre
原子
中以供以后显示来解决这个问题。但是我不理解为什么基于简单共享内存的版本不能正常工作:每个线程使用自己的计数器,因此没有竞速条件。即使显示线程也仅在计数线程完成后访问计数器。使用volatile
也没有帮助
有谁能解释我这种奇怪的行为(好像记忆没有更新)并告诉我是否遗漏了什么
以下是共享变量:
const int maxthread = 6;
atomic<bool> other_finished = false;
atomic<long> acounter[maxthread];
以下是重现问题的简化版本:
void deep_thought(int& value) { value = 6 * 9; }
int main()
{
int answer = 42;
std::thread{deep_thought, answer).join();
return answer; // 42
}
它看起来像是将对answer
的引用传递给worker函数,并将6*9
分配给引用,从而分配给answer
。但是,std::thread
的构造函数复制了answer
的一个副本,并将副本的引用传递给辅助函数,并且主线程中的变量answer
从未更改
GCC-4.9和Clang-3.5都拒绝上述代码,因为不能使用左值引用调用辅助函数。您可以通过使用std::ref
传递变量来解决此问题:
std::thread{deep_thought, std::ref(answer)}.join();
以下是重现问题的简化版本:
void deep_thought(int& value) { value = 6 * 9; }
int main()
{
int answer = 42;
std::thread{deep_thought, answer).join();
return answer; // 42
}
它看起来像是将对answer
的引用传递给worker函数,并将6*9
分配给引用,从而分配给answer
。但是,std::thread
的构造函数复制了answer
的一个副本,并将副本的引用传递给辅助函数,并且主线程中的变量answer
从未更改
GCC-4.9和Clang-3.5都拒绝上述代码,因为不能使用左值引用调用辅助函数。您可以通过使用std::ref
传递变量来解决此问题:
std::thread{deep_thought, std::ref(answer)}.join();
对抱歉:Win 8.1上的MSVC 2013,与intel i7几乎不可能与此问题相关。但是,关于性能,您应该看一看,即不同的线程不应该写入同一缓存线上的变量,在您的例子中是
counter
。关于错误共享的非常有趣的文章。我怀疑缓存有问题。但是,在您使用std::ref()解决方案之后,我使用全局数组创建了我的程序的一个vriant,并且没有引用传递。这很好,这证实了问题不是缓存而是引用。是的!抱歉:Win 8.1上的MSVC 2013,与intel i7几乎不可能与此问题相关。但是,关于性能,您应该看一看,即不同的线程不应该写入同一缓存线上的变量,在您的例子中是counter
。关于错误共享的非常有趣的文章。我怀疑缓存有问题。但是,在您使用std::ref()解决方案之后,我使用全局数组创建了我的程序的一个vriant,并且没有引用传递。这很好,这证实了问题不在于缓存,而在于引用。可能需要提到的是,解决方案是使用std::reference\u包装器
@T.C.:感谢您的提示。我已经更新了答案。可能需要提到的是,解决方案是使用std::reference\u包装器
@T.C.:谢谢你的提示。我已经更新了答案。
std::thread{deep_thought, std::ref(answer)}.join();