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.
Do you want to remove this version name and description?
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