当我发现“CAS”指令时,我记得我很清楚它可以用于在单个CPU上运行的线程,但我很惊讶它可以用于许多CPU
昨天,我第一次有机会在我的一项开发项目上进行测试。我实现了它,它确实工作正常;我所有的单元测试都是绿色的。完美。
但今天,我在另一台机器上运行了我的单元测试,现在他们失败了。不太完美
两台机器的主要区别在于第一台(单元测试为绿色的机器)是退出旧笔记本电脑,只有一个核心!第二个是最近的i7,更强大......
现在,在我的i7上,如果我强制我的单元测试在一个核心上运行,它们就会成功。我这样做是通过运行
taskset -c <cpu-id> my-unit-test
合法地说,我的原始问题又回来了:CAS是否在许多内核上工作?好的,根据我读到的内容,如果没有,我会感到惊讶......
那又怎样?我希望它来自我的代码中的错误。为了给你提供更多信息,我有一个关键部分的课程。我添加了一个属性
bool m_isBeingModified;
它被初始化为false
。而且,在我的关键部分的开头,我运行了函数
inline void waitForClassBeingModified()
{
while (!__sync_bool_compare_and_swap(&m_isBeingModified, false, true))
{} /// I concider that I can to such a loop as my critical section is very light/short
}
最后,在我的关键部分结束时,我重置了我的布尔变量
m_isBeingModified = false;
我尝试将我的属性设置为volatile
,但它没有改变任何内容:我的单元测试仍然失败
最后信息:
gcc --version
gcc (Ubuntu 6.2.0-5ubuntu12) 6.2.0 20161005
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
感谢您的帮助
答案 0 :(得分:2)
还可以使用__sync_bool_compare_and_swap
取消设置变量,而不仅仅是m_isBeingModified = false;
。另外,不要实现自己的互斥锁......
编译器和CPU都可以以非预期的方式重新排序代码。 __sync
原语以这样的方式标记,以防止这种重新排序的快乐。因此,对于m_isBeingModified = false;
,编译器首先将变量设置为false
,然后只为您想要在关键区域内生成的代码生成代码。
答案 1 :(得分:0)
感谢Uli的宝贵帮助,我认为现在我已经有了回答我问题的所有要素。
首先,我可能不清楚,但我希望防止并发访问的功能非常轻。完成需要大约80个cpu周期(TSC)。这就是为什么我更愿意实施自己的“光线”&#39;并发互斥基于一个CAS,而不是使用pthread_mutex
。
我发现this interesting page解释了如何暂时&#39;由于以下说明,禁用代码重新排序:
__asm__ __volatile__("":::"memory");
使用它,我真的提升了我的并发保护,当然我所有的测试仍然是成功的。
要获得摘要,以下列表会报告我尝试的不同解决方案对性能的影响: