Ale*_*lex 3 c++ concurrency multithreading x86-64 c++11
MFENCE。\n\n\n8.2.3.4 可以将早期存储的负载重新排序到不同位置
\n
c.store(relaxed)<--> b.load(seq_cst):https ://stackoverflow.com/a/42857017/1558037
// Atomic load-store\nvoid test() {\n std::atomic<int> b, c;\n c.store(4, std::memory_order_relaxed); // movl 4,[c];\n int tmp = b.load(std::memory_order_seq_cst); // movl [b],[tmp];\n}\nRun Code Online (Sandbox Code Playgroud)\n\n可以重新排序为:
\n\n// Atomic load-store\nvoid test() {\n std::atomic<int> b, c;\n int tmp = b.load(std::memory_order_seq_cst); // movl [b],[tmp];\n c.store(4, std::memory_order_relaxed); // movl 4,[c];\n}\nRun Code Online (Sandbox Code Playgroud)\n\nMFENCE因为, x86_64 上没有:
但是是否有一个真正有效的示例可以显示 x86_64 上存储加载重新排序的副作用?
\n\n例如,使用时显示正确的结果Store(seq_cst), Load(seq_cst),但使用时显示错误的结果Store(relaxed), Load(seq_cst)。
或者 x86_64 上是否允许存储加载重新排序,因为它无法在程序中检测和显示?
\n是的,有 C++11 和 x86_64 上存储加载重新排序的示例。
首先,我们严格证明我们代码的正确性。然后在这段代码中,我们将移除mfenceSTORE 和 LOAD 之间的障碍,并看到算法崩溃了。
有一个自定义锁(自旋锁),其实现无需 CAS/RMW 操作,仅对有限数量的线程进行加载和存储,其中每个线程编号 0-4:
// example of Store-Load reordering if used: store(release)
struct lock_t {
static const size_t max_locks = 5;
std::atomic<int> locks[max_locks];
bool lock(size_t const thread_id) {
locks[thread_id].store(1, std::memory_order_seq_cst); // Store
// store(seq_cst): mov; mfence;
// store(release): mov;
for (size_t i = 0; i < max_locks; ++i)
if (locks[i].load(std::memory_order_seq_cst) > 0 && i != thread_id) { // Load
locks[thread_id].store(0, std::memory_order_release); // undo lock
return false;
}
return true;
}
void unlock(size_t const thread_id) {
locks[thread_id].store(0, std::memory_order_release);
}
};
Run Code Online (Sandbox Code Playgroud)
acquire-release-语义:然后我们将展示如何分解我们的锁定算法 -结果应该是: 20000:
C++ 差异:
然后我们展示一下汇编代码的区别:
mfence):https://godbolt.org/g/WrCiyWmfence): https: //godbolt.org/g/Eo3TXRAsm x86_64 差异:
因为它是经过严格证明的,一个“好”的算法是正确的。因为我们看到“坏”算法无法正常工作(结果 19976 不等于 20000)。mfence它们之间唯一的区别是 - STORE 和 LOAD 之间的障碍。因此,我们提供了发生存储加载重新排序的算法。
另外,至少有一个存储-加载重新排序的示例 -这有点像我们的示例:x86 可以使用完全包含它的更宽的加载来重新排序一个狭窄的存储吗?
| 归档时间: |
|
| 查看次数: |
512 次 |
| 最近记录: |