embedded
contributed by <Cayonliow
>
可是依上圖, Perf/Clock(ILP), Power 跟 Clock Speed 在 2000 年就出現飽和的現象, 所以增進效能的手段也跟着改變
現在 CPU 增進效能的手段
Free (performance) lunch 指的是程式設計的效能可以透過 CPU 時脈的進步而得到改善。會說 over 是因為 CPU 的時脈無法得到更進一步的增加,由於耗電和散熱的問題,所以程式設計師必須要修改程式才能改善效能
使用 Concurrency 的理由:
1.分離可獨立運作的工作;
2.為了效能,像是使用多核新的 CPU
可是並非所有的程式都合適平行化;所以程式要設計可以實行 Concurrency 是很困難的
如果程式的相依性太高或是太常取用共同資源則會拖慢 Concurrency 的效率
對軟體設計的影響
A happends-before B : 在 B 開始執行之前, A 的執行效果必須可見。
A is Sequenced-Before B : 在同一個 thread 下,A 比 B 先求值。
A is synchronized-with B : A 在這一個 thread 對記憶體的操作,在另一個 thread 的 B 必須可見。
Sequential consistency : 無論處理器實際怎麼執行,確保結果跟照程式順序執行一樣
Concurrency is not parallelism
Concurrency 是指程式架構, 將程式拆開成多個可獨立運作的工作
eg:drivers, 都可以獨立運作,但不需要平行化。
拆開多個的工作不一定要同時運行
多個工作在單核心 CPU 上運行
工作可拆分成「獨立執行」的部份, 這樣「可以」讓很多事情一起做, 但是「不一定」要真的同時做。
展示具有並行性,但不去同時執行
並行性是種「架構程式」的概念。寫下一段程式之前, 思考問題架構時就決定好的。
Parallelism 是指程式執行, 同時執行多個程式. Concurrency 可能會用到 parallelism,但不一定要用 parallelism 才能實現 concurrency。
一開始先 make plot 看看結果
append()
的效能提升了很多, 所用的時間甚至比 findName()
來的少然後參考 csielee 的共筆 分析 concurrent 的實作
主要是在 append() 的時候將工作分給多個 thread 一起做
並使用下面的方法,讓多個 thread 可以順利 concurrent
DICT_FILE
(要讀取的名字檔案)O_RDONLY
: 以只讀方式打開文件O_NONBLOCK
:以不可阻斷的方式打開文件,也就是無論有無數據讀取或等待,都會立即返回進程之中 text_align(DICT_FILE, ALIGN_FILE, MAX_LAST_NAME_SIZE);
int fd = open(ALIGN_FILE, O_RDONLY | O_NONBLOCK);
off_t file_size = fsize(ALIGN_FILE);
ALIGN_FILE
的檔案內容利用 mmap() 記憶體對映到記憶體當中PROT_READ
:映射區域可被讀取PROT_WRITE
:映射區域可被寫入MAP_PRIVATE
:對應射區域的寫入操作會產生一個映射文件的複制,即私人的“寫入時復制”(copy on write)對此區域作的任何修改都不會寫回原來的文件內容 。 map = mmap(NULL, file_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
assert(map && "mmap error");
entry_pool = (entry *)malloc(sizeof(entry) *
file_size / MAX_LAST_NAME_SIZE);
assert(entry_pool && "entry_pool error");
for (int i = 0; i < THREAD_NUM; i++)
// Created by malloc, remeber to free them.
thread_args[i] = createThead_arg(map + MAX_LAST_NAME_SIZE * i, map + file_size, i,
THREAD_NUM, entry_pool + i);
for (int i = 0; i < THREAD_NUM; i++) {
if (i == 0) {
pHead = thread_args[i]->lEntry_head->pNext;
DEBUG_LOG("Connect %d head string %s %p\n", i,
pHead->lastName, thread_args[i]->data_begin);
} else {
e->pNext = thread_args[i]->lEntry_head->pNext;
DEBUG_LOG("Connect %d head string %s %p\n", i,
e->pNext->lastName, thread_args[i]->data_begin);
}
e = thread_args[i]->lEntry_tail;
DEBUG_LOG("Connect %d tail string %s %p\n", i,
e->lastName, thread_args[i]->data_begin);