[英]In C++11 or later is there a way to have a constexpr that determines endian without UB?
[英]Data races, UB, and counters in C++11
以下模式在許多軟件中很常見,這些軟件想告訴用戶它做了多少事情:
int num_times_done_it; // global
void doit() {
++num_times_done_it;
// do something
}
void report_stats() {
printf("called doit %i times\n", num_times_done_it);
// and probably some other stuff too
}
不幸的是,如果多個線程可以調用doit
沒有某種形式的同步,並發讀-修改-寫入num_times_done_it
可能是一個數據的比賽,因此整個程序的行為將是不確定的。 此外,如果report_stats
可以同時使用稱為doit
缺席任何同步,還有線程修改之間的另一數據競爭num_times_done_it
和線程報告其價值。
通常,程序員只想要盡可能少的開銷來調用doit
的次數。
(如果你認為這個例子是微不足道的, Hogwild!比使用基本上這個技巧的數據無競爭隨機梯度下降獲得了顯着的速度優勢。而且,我相信Hotspot JVM正是這種無人看守,多線程訪問共享計數器對於方法調用計數---雖然它是明確的,因為它生成匯編代碼而不是C ++ 11。)
明顯的非解決方案:
volatile
會使數據num_times_done_it
正常,所以用volatile int num_times_done_it
替換num_times_done_it
的聲明並不能解決任何問題。 report_stats
,但這並不解決之間的數據爭doit
和report_stats
。 此外,它很混亂,它假設更新是關聯的,並不真正適合Hogwild!的用法。 是否有可能在一個非平凡的多線程C ++ 11程序中實現具有良好定義語義的調用計數器,而無需某種形式的同步?
編輯 :似乎我們可以使用memory_order_relaxed
以稍微間接的方式執行此memory_order_relaxed
:
atomic<int> num_times_done_it;
void doit() {
num_times_done_it.store(1 + num_times_done_it.load(memory_order_relaxed),
memory_order_relaxed);
// as before
}
但是, gcc 4.8.2
在x86_64(帶-O3)上生成此代碼:
0: 8b 05 00 00 00 00 mov 0x0(%rip),%eax
6: 83 c0 01 add $0x1,%eax
9: 89 05 00 00 00 00 mov %eax,0x0(%rip)
和clang 3.4
在x86_64上生成此代碼(再次使用-O3):
0: 8b 05 00 00 00 00 mov 0x0(%rip),%eax
6: ff c0 inc %eax
8: 89 05 00 00 00 00 mov %eax,0x0(%rip)
我對x86-TSO的理解是這兩個代碼序列都禁止中斷和有趣的頁面保護標志,完全等同於單指令存儲器inc
和由簡單代碼生成的單指令存儲器add
。 memory_order_relaxed
使用是否構成數據競爭?
分別計算每個線程,並在線程加入后總結。 對於中間結果,您也可以在兩者之間進行總結,但結果可能會關閉。 這種模式也更快。 您可以將它嵌入到線程的基本幫助器類中,這樣如果您經常使用它,就可以使用它。
並且 - 取決於編譯器和平台,原子並不那么昂貴(參見Herb Sutters“原子武器”談話http://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Herb-Sutter -atomic-Weapons-1-of-2 )但在你的情況下,它會產生緩存問題,所以這是不可取的。
似乎memory_order_relaxed
技巧是正確的方法。
英特爾的Dmitry Vyukov撰寫的這篇博文首先回答了我的問題,並繼續列出memory_order_relaxed
store
並load
為正確的選擇。
我仍然不確定這是否真的好; 特別是, N3710讓我懷疑我是否曾首先理解memory_order_relaxed
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.