or
or
By clicking below, you agree to our terms of service.
New to HackMD? Sign up
Syntax | Example | Reference | |
---|---|---|---|
# Header | Header | 基本排版 | |
- Unordered List |
|
||
1. Ordered List |
|
||
- [ ] Todo List |
|
||
> Blockquote | Blockquote |
||
**Bold font** | Bold font | ||
*Italics font* | Italics font | ||
~~Strikethrough~~ | |||
19^th^ | 19th | ||
H~2~O | H2O | ||
++Inserted text++ | Inserted text | ||
==Marked text== | Marked text | ||
[link text](https:// "title") | Link | ||
 | Image | ||
`Code` | Code |
在筆記中貼入程式碼 | |
```javascript var i = 0; ``` |
|
||
:smile: | ![]() |
Emoji list | |
{%youtube youtube_id %} | Externals | ||
$L^aT_eX$ | LaTeX | ||
:::info This is a alert area. ::: |
This is a alert area. |
On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?
Please give us some advice and help us improve HackMD.
Syncing
xxxxxxxxxx
從 C++11 規格和 Template Meta-Programming 的角度欣賞 Boost 對 atomic 和 memory order 的支援 - 翁敏維
由於場地問題,第二天我們移動到另一棟大樓啦!議程教室變動請見網站上的議程表。
歡迎來到 https://hackmd.io/@coscup/2019 共筆
- The image file may be corrupted
- The server hosting the image is unavailable
- The image path is incorrect
- The image format is not supported
Learn More →點擊本頁上方的 開始用 Markdown 一起寫筆記!
手機版請點選上方 按鈕展開議程列表。
簡報模式
Agenda
Introduction
為什麼要看 C++11 規格?
Reference
Boost.Atomic, Usage example
上面這段節錄自 Boost.Atomic, Usage example,由於直接看 code 並不是有效率的學習方式,甚至可能得到錯誤的認知,所以從理解 C++11 規格開始。
透過理解 C++11 規格,看到上面這段 code 就不必用猜的,也不必用 try and error ,是一種比較有效率的學習路線。
Why needs Template metaprogramming?
先澄清一件事,
不是直接用 templates 程式就會變快。
雖然 template 會在 compile-time 作展開和運算,但如果 僅僅只是 直接把 function 改成 template,就如同直接換成 inline 或 macro一樣,執行的時間是沒有差別的
作一個實驗來說明這個概念
並不是 templates 不會讓執行時間縮短,而是因為剛剛的測試範例只是直接把 function 換成 templates
用 templates 實作出在 compile-time 運算來縮短執行時間,同時具有 inline 和 macro 所不具有的優點,並不是這一次 talk 的主題
那 template metaprogramming 要探討什麼?
有。
write generic code
用對照組,體會一下是不是 generic code 的差異
這段看起來,我們可能會這麼覺得:
剛剛我們示範了一個讓人用 覺得 來判斷的 code,這在可讀性上來說,實在不妥
或許可以用加註解來解決可讀性,
不過上面這個例子有更好的解法
更好的解決方法是 write generic code,所以我們用 templates metaprogramming,修改後是這樣子
當然,我們假設上面的例子,每一個 calc 的計算方式一樣
What is memory order?
reorder
a, b, c, d 的執行順序有沒有可能是 b, d, c, a
由於 CPU 會進行 reorder,所以未必會照著順序執行,因此在這個範例中,processor 0 的 EAX 和 processor 1 的 EAX 有可能都是 0 (只是經過測試,100 萬次裡出現的次數是個位數)
reorder 在不同的 CPU 會有不一樣的行為
reorder 之後 有可能 是照著這個順序執行
compiler 會對 program order 作 reorder,而 CPU 也會對 instruction 執行的順序作 reorder。
阻止全部的 reorder 雖然也是一種方法,但這樣會產生 效率低落 的結果。所以需要研究 memory order,讓工程師能對 reorder 作一些控制。
out-of-order
我們從 instruction pipelining 來理解 out-of-order
in-order
如果是照著以上的順序來執行 2 個 instruction,會用掉 8 個 cycle 來執行 2 個 instruction。
out-of-order
但如果是 OoOE,可能會是以下的順序,這樣就可以只用 5 個 cycle 執行 2 個 instruction
但是 out-of-order 會有一個延伸的問題,
execute2
如果會從 register 讀取一個值,而這個值要write1
執行後才會更新…那
execute2
的結果?現在我們知道 program order 是我們從 source code 看到的順序,但是實際執行的順序,未必和 program order 一樣。
CPU 會對 instruction 作 reordering,所以我們看到的 assembly 的 program order 未必是執行順序
如果我們寫的是 C++11 的 code,program order 是不是也有可能不一樣?
對,program order 是允許不一樣的,但 C++11 支援不同的 memory order,可以控制實際執行順序
How C++11 supports memory order?
從 C++11 規格來看 data races
C++11 1.10/21
The execution of a program contains a data race if it contains two conflicting actions in different threads, at least one of which is not atomic, and neither happens before the other.
Reference
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3376.pdf
其中一個 thread 的 operation 不是 atomic operation,而且也沒有 happens before 這種關係
A synchronization operation on one or more memory locations is either a consume operation, an acquire operation, a release operation, or both an acquire and release operation.
Reference
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3376.pdf#section.1.10
synchronization operation 是要在不同的執行緒之間同步,等一下我們會在範例中看到這是如何運作的
在 wait-free multi-producer queue 會用到 memory_order_relaxed、memory_order_release 和 memory_order_consume
wait-free multi-producer queue 就是一開始提到的 Boost 的範例
特別要留意的地方是:
relaxed operations 雖然是 atomic,但不是 synchronization operations
In addition, there are relaxed atomic operations, which are not synchronization operations, and atomic read modify-write operations
Reference
C++11 1.10 Multi-threaded executions and data races
C++11, page 1115 說明了 memory_order_seq_cst 是一種 single total order
consistent with the “happens before” order and modification orders for all affected locations
因為 memory_order_seq_cst 會維持所有執行緒的同步,考慮到效能,所以需要再理解其他的 memor order,例如接下來要探討的 memory_order_relaxed 、memory_order_release 和 memory_order_consume。
Reference:
C++11 規格, page 1116
有沒有可能最後的結果是 r1 = r2 = 42?
因為 memory_order_relaxed 只是 atomic operaion 不是 synchronization operations
所以執行順序有可能是這樣
Reference:
C++11 規格, page 1116
Boost.Atomic
Example about atomic
第 5 、8 行的 load、compare_exchange_weak 就是 atomic operation,底下會再討論到這兩個 atomic operation,也會提到 3 個 memory order:memory_order_relaxed、memory_order_release 和 memory_order_consume。
Reference
Boost.Atomic, Usage examples
C++11, page 1124 對 compare_exchange_weak 是這麼說的
Implementations should ensure that weak compare-and-exchange operations do not consistently return false unless either the atomic object has value different from expected or there are concurrent modifications to the atomic object.
memory_order_release v.s. memory_order_consume
Boost 是這麼說的
The use of memory_order_release after creating and initializing the object and memory_order_consume before dereferencing the object provides this guarantee.
再看看 C++11, page 1114 怎麼說
memory_order_release, memory_order_acq_rel, and memory_order_seq_cst:
a store operation performs a release operation on the affected memory location.
memory_order_consume:
a load operation performs a consume operation on the affected memorylocation
如果用 memory_order_acquire 來理解 memory_order_consume,會容易點,但是 memory_order_consume 不等於 memory_order_acquire
可以把 memory_order_consume 換成 memory_order_acquire,但不能把 memory_order_acquire 換成 memory_order_consume
透過 memory_order_release、memory_order_consume 建立了 happens-before 的關係
Boost.Atomic
multi-producer and single consumer queue
producer–consumer problem 基本上分這幾種
由於 producer–consumer problem 不是這裡的重點,
所以只會講到所以只會講到 multi-producer and single consumer
multi-producer and single consumer queue
producer 會 push message 到 queue ,然後 consumer 會將 queue 裡的 message 取走
queue 是一個先進先出的 FIFO, First-In-First-Out 的資料結構,但是如果加了在多執行緒下有多個 producer 同時 push to queue,情況就有點複雜
節錄自 Boost.Atomic, Usage example
現在再看這個範例,是不是就可以不用靠 try and error 跟猜測了?
Reference
Boost.Atomic, Usage example, multi-producer queue
Reference
END
tags:
COSCUP2019
帶您讀源碼
IE2102
tags:
C++11
memory order
TMP
Template Meta-Programming
Boost
atomic
Boost.Atomic
1.66