星期四, 1月 17, 2013

悖論


第一次看到悖論﹙paradox﹚這個詞是在Final Fantasy XIII-2,今天晚上看到第到第二次,居然是在講儲存的書裡。悖論[1]指的應該是︰
如果承认它是真的,经过一系列正确的推理,却又得出它是假的;如果承认它是假的,经过一系列正确的推理,却又得出它是真的。
不知道該說是FF XIII-2太深奧了,還是書扯太遠了。

[1] 悖论, http://zh.wikipedia.org/wiki/悖論

星期一, 1月 14, 2013

今天就以False-sharing就做為一天的結束吧

電腦上的儲存裝置的速度,暫存器﹙register﹚ > cache﹙快取﹚> RAM﹙Random-access memory﹚ > blah...blah...blah...

這篇文章的主題是cache,cache line是CPU管理cache的單位,有數種方法可以取得cache的大小[1]。在寫程式的時候,需要盡量保持資料在cache裡,這樣程式可以跑的比較快。

在multi-core的環境下,cache管理機制﹙MESI [2]﹚裡隱藏著一個陷阱,False-sharing。

False-sharing是指程式以multi-thread(process)的模式在存取資料時,意外造成cache invalidate,然後導致效能下降﹙因為要重新讀取資料更新cache﹚。

引用wiki[3]上的範例來看,
struct foo {
  int x;
  int y;
};

static struct foo f;

/* The two following functions are running concurrently: */

int sum_a(void)
{
  int s = 0;
  int i;
  for (i = 0; i < 1000000; ++i)
    s += f.x;
  return s;
}

void inc_b(void)
{
  int i;
  for (i = 0; i < 1000000; ++i)
    ++f.y;
}
兩個threads,一個執行sum_a﹙讀取f.x﹚,另一個執行inc_b﹙更新f.y﹚,兩個threads貌似彼此獨立,但,實際上卻因為f被分別塞進兩個CPUs的cache line,一邊不斷的更新,造成另一邊的cache invalidate,然後更新CPU cache,時間就無形的浪費了。但,這是可以解決的,[4, 5]列出了可能的解法。但,記得先profile[6],確定你的cache miss問題嚴不嚴重!

隨著nVIDIA在CES展上發表了Tegra 4[7],手動手持裝置﹙嵌入式系統?﹚也進入了很多核時代﹙其實早就雙核了啦﹚。撰寫程式時就需要知道這些雜七雜八的事。

但,話說回來,JavaScript / Python / Ruby / Lua,這種script language,要怎麼做才能控制到這種細節?

[1] Programmatically get the cache line size?,http://stackoverflow.com/questions/794632/programmatically-get-the-cache-line-size
[2] MESI protocol, http://en.wikipedia.org/wiki/MESI_protocol
[3] False sharing, http://en.wikipedia.org/wiki/False_sharing
[4] False sharing問題及其解决方法,http://rritw.com/a/JAVAbiancheng/thread/2011/0604/87966.html
[5] 多核平台下Cache的False Sharing问题 ,http://blog.csdn.net/duofeng/article/details/1525876
[6] Are there any way to profile cache miss in linux kernel?,http://stackoverflow.com/questions/9394193/are-there-any-way-to-profile-cache-miss-in-linux-kernel
[7] 輝達Tegra 4亮眼 台積電代工,http://news.chinatimes.com/tech/171706/122013010800435.html

星期日, 11月 04, 2012

不能用valgrind,用mtrace總可以了吧!

在嵌入式系統上,因為valgrind並不支援armv5﹙但,支援armv7﹚,所以,在抓memory leak時,有時會porting到x86上用Valgrind掃一次,能找多少修多少。但,有時還是會發生慘案,在x86上掃不出,可是,放到板子上跑時,卻會memory leak。

儘管[1]舉出數個可應用在embedded systems上的detectors,但,找不到因不慎操作shared library產生的memory leak。比如,不斷呼叫GLib GList的append/prepend卻忘了釋放,雖然GLib支援透過環境變數改變GSlice的行為,變為直接呼叫malloc。可是,像mtrace這類的工具,只會回報shared library裡面有呼叫malloc,但,卻無法透過addr2line找出memory leak的地方。

所以,產生了一個想法,自己寫一個簡單的shared library,透過掛載malloc hooks,在每一次malloc被呼叫時,使用backtrace找出當時的callstack,程式結束時,把結果寫到檔案。在搜尋撰寫library相關知識時發現,其實已經有人寫好了libmtrace,也可以卻實找出當下的callstack,算是符合當初預期的目標。太好了,省事多了XD

[1] Memory Leak Detection in Embedded Systems

星期日, 10月 14, 2012

Markdown語法說明與線上編輯

最近看了一下Markdown語法[1],其實和wiki的語法很像,都可以用純文字的方式撰寫再轉成HTML。有好心人提供了線上編輯工具[2],同時提供了轉換後的source code和preview兩種功能。

[1] Markdown語法說明, http://markdown.tw/
[2] Markdown Web Dingus, http://daringfireball.net/projects/markdown/dingus

星期日, 9月 23, 2012

socket zero-copy

一直好奇socket能不能在user-mode和kernel-mode之間達成zero-copy[1,2],看起來是可以的。

一開始是看到Linux PACKET_MMAP[3],但,PACKET_MMAP是用來做packet capture的,如果拿來做實作像RTSP的串流協定,得先花很多工夫在實作TCP這類底層的協定,光想就覺得很累。

再試著搜尋一下,也許可以透過splice[4]達成,只是較不直覺。

方法是先建一個檔案﹙也許用fallocate﹚,然後開啟檔案並用mmap對映至行程空間,接下來就是用splice把資料搬至檔案,然後用透過mmap取得的指標操作資料。簡單的表示就是︰
socket fd -> write end pipe -> read end pipe -> file fd


[1] Linux 中的零拷贝技术,第 1 部分, http://www.ibm.com/developerworks/cn/linux/l-cn-zerocopy1/index.html

[2] Linux 中的零拷贝技术,第 2 部分, http://www.ibm.com/developerworks/cn/linux/l-cn-zerocopy2/index.html

[3] Raw socket, Packet socket and Zero copy networking in Linux, http://yusufonlinux.blogspot.tw/2010/11/data-link-access-and-zero-copy.html

[4] splice(2) - Linux man page, http://linux.die.net/man/2/splice

09/30更新

文章[5]講的更貼近實務,而文章[6]說明如何調整pipe大小

[5] splice(), http://ogris.de/howtos/splice.html

[6] 深入理解PIPE, http://blog.ddup.us/?p=285