2013/4/15

2013 google code jam 試題A-small,B-small,C-small分析A-large,B-large,C-large-1解析

人生但求及格就好... 寫到四點愛睏 就去睡了...

2013 google code jam資格賽,
A. Tic-Tac-Toe-Tomek

B. Lawnmower

C. Fair and Square

D. Treasure

 


第一二題考矩陣迴圈,速解的關鍵在於化做2進位,bit-1X , bit-2y, 很自然的T就是bit-1 + bit-2


第三題考超大整數物件,large-1需用64bit integer才能處裡到15位正整數,large-2需用巨大整數class來解,所以要先寫或去抓一個這樣的class,所以這次全對的機乎都是用javac++smalllarge-1速解在於查表,15位正整數內的可能性只有39,先算好在一個integer array後來在查表即可。


第四題考先深搜尋法,然後可能要用到其它資料結構所以機乎都是用javac++,但這一題我沒有解,所想前面應該有35分所以去睡了。


滿分250分,對35分就可以晉級,
台灣六個全對者,五個使用C++,一位用Java

 

官方的解釋說明: (我還沒有看,有空我會寫第四題看看)

https://code.google.com/codejam/contest/2270488/dashboard#s=a&a=4

 

至於到底有沒有17k這麼多人完成資格賽,個人覺得沒有,而且拿35分狀況只有去解CLarge-1

這題剛好35分,但可以解CLarge-1,就可以解Csmall,這兩個小題的演算法是一樣的,只差在知不知道怎麼宣告long long這個64位元整數,所以拿35分的人一整個是故意的,也就是不是45分就是0分,這題沒有在拿35分的,而又或者,這根本就是多開帳號來解big data的。

 

沒有17k那麼多人啦,因為拿了large data file後,8min內要上傳result file,且只有一次上傳機會,所以大家都會多開帳號先去拿data file

 

像我自己就有三個帳號過資格賽。

2013 google code jam試題分析

人生但求及格就好... 寫到四點愛睏 就去睡了...

2013 google code jam資格賽,
A. Tic-Tac-Toe-Tomek

B. Lawnmower

C. Fair and Square

D. Treasure

 


第一二題考矩陣迴圈,
第三題考超大整數物件,
第四題考先深搜尋法。

滿分250分,對35分就可以晉級,
台灣六個全對者,五個使用C++,一位用Java

 

官方的解釋說明:

https://code.google.com/codejam/contest/2270488/dashboard#s=a&a=4

可以玩樂器的chrome網頁 jam with chrome

Intel最新IT年報及行動裝置管理解決方案!

搭乘大眾運輸工具或等待用餐的閒暇時間,都能使用自己的行動裝置來處理公務,以及構思軟體的最佳解決方案,甚至於想出優秀的演算法,

 

 

活動期間

即日起-10253

活動方式

凡完整填寫問卷並成功提交者,就有機會獲得Intel獨家隨身碟,更有機會免費試用Ultrabook™或Windows* 8平板電腦!

獎項

Ultrabook™ 或 Windows* 8平板免費試用體驗服務 2
Intel
隨身碟 150

活動注意事項

1. 本活動由美商英特爾台灣分公司主辦,試用服務以及贈品均由美商英特爾台灣分公司提供。
2.
美商英特爾台灣分公司具有審核申請資格及保留擴大、變更修改或終止本活動之權利,無須事前通知。
3.
活動結束後將由美商英特爾台灣分公司或其委託單位個別連絡得獎者。
4.
其他未盡事宜,悉依主辦單位相關規定。
5.
活動若發生任何爭議,概以主辦單位美商英特爾台灣分公司之決定為準。

以下欄位*號者為必填

表單的頂端

姓名*

公司*

職銜*

連絡電話(公司) * (範例:02-23456789#3365

連絡電話(手機)  (範例:0912345678

電子郵件* (請勿填寫yahoo, hotmail, gmail等免費信箱)

聯絡地址*

1. 請問您所服務的公司規模(非公司內的單位)*
10人以下  11-49人  50-99人  100-149
150-199
人  200-499人  500人以上

2. 請問貴公司主要的營業性質?*
生產製造業  零售流通  金融服務  電子/通訊  政府/非營利單位
學術暨研究單位  其他
 

3. 請問您上班時會使用個人的行動裝置嗎?*
是  

4. 請問您目前最常使用的行動商務服務或APP為? (複選)*
E-mail  通訊軟體(LineWhatsAPP)  文書處理  公司內部系統  設備監控系統
其他
 

5. 請問貴公司目前已導入哪些行動裝置管理計畫? (複選)*
Notebook  Ultrabook   平板  智慧型手機  目前無導入相關計畫 
其他
 

6. 若未導入,請問貴公司是否有導入行動裝置管理之計畫?*
已導入 有,預計於 月內導入  沒有

7. 請問對貴公司來說,導入BYOD過程中您最在意的是?(複選)*
資訊安全  資料傳輸速度 處理效率  導入成本  介面是否對使用者友善 
其他

8. 請您分享對於使用BYOD的心得(100字以內)

您同意於本頁載明之活動注意事項。

您同意美商英特爾台灣分公司得於特定目的範圍內蒐集、處理及利用您參加本次活動所提供之個人資料,並得定期或不定期寄發美商英特爾台灣分公司或其之客戶所委託寄發的各類活動、課程及產品行銷有關之eDM或與商品或服務有關之訊息或行銷宣傳品至您於活動報名過程中所填寫的聯絡地址及電子郵件信箱,並接收到來自美商英特爾台灣分公司或其委託單位之電話訪談聯絡。

感謝您抽空填寫問卷,祝您幸運中獎! 
請至以下連結立即下載Intel最新IT年報及行動裝置管理解決方案!

 

2013/4/14

華碩ASUS padfone infinity 預購單 中華電信 遠傳電信 台灣大哥大 威寶電信


這已經是第二次來上padfone infinity android英文家教班了,
為了替家裡節省昂貴的ASUS家教費用,
而來上這種動不動就兩三百人的大型補習班,
這個教室當然很大,在劃位置時,因為位置週圍都沒有人坐,
所以第一次上課做位置時,我只計算一個大概,
因為黑板很遠 就坐在大約第七排的位置,
但是上課時,陸陸續續有三個ASUS女生坐到我前面來了,
是不是我坐到本來她們的位置?

ASUS Padfone Infinity, Android, Fonepad,

出乎意料地,中間那個姑娘還真可人,
雖然沒有一頭長髮,
但那雙迷人的大眼睛,真叫人ASUS著迷,
皮膚也是光滑細緻,
上課時,眼睛總是忍不住飄了過去,
不知道她有沒有察覺?有沒帶來甚麼她的困擾?
一次上課三個半小時?但第一次覺得補習時間真短?
愛因斯坦說時間是相對的,不是絕對的,有美女讓上課時間變短。

她的頭髮長度正好,再肩膀跟腰由上面下來三分之二的位置,
格子狀的藍色上衣,褲子有一件吊帶褲,下面到膝蓋,現在很少人穿吊帶褲了,
不過她穿就是特別好看,對了,那天她背的背包是透明的。

就連老師也要虧,老師也做的太太太明顯囉!
竟然在課堂上虧起她來了,問她甚麼學校的!
還暗喻她長得很漂亮,說她也原住民的隔代遺傳,
不過她說她沒有,老師還故意借她的書,說她的男朋友叫經理,
那是剛剛抄下來英文單字好不好。

第二個星期,她在大樓下面隔兩間的便利商店裡買Android包子,
這是我最接近她的一次,我先進去買牛奶,故意走得很慢,
深怕她結完帳就走囉!原來她再夾包子啊!
她夾得很慢,所以我可以偷看她Padfone Infinity,她夾完Padfone Infinity包子,把夾子地給我!

第三週,她一個朋友過來跟她聊天,我便趴在桌上假裝休息聽她講話,不知道是說誰在等公車?
還有說訂甚麼ASUS magazine的,她說:「我也想訂耶,不過很貴捏,Android一個月要100多塊!」
還說甚麼電腦,又Padfone Infinity視窗版的,這時我似乎可以臭屁一下!不過我沒有!

陸陸續續好幾個星期都坐在她們Padfone Infinity後面,
不過這一個星期我比較晚到,到教室時,
金魚眼已經就定位Padfone Infinity了,坐在我原來的位置旁邊,
不過我可沒膽量去坐在金魚眼的旁邊,金魚眼也不是坐在我的位置上,
我也不能夠說「對不起!同學,這是我的Android位置。」吧?

我只好去最後一排找高怪,高怪是我的同班同學!
金魚眼就是說不上的好看,其實她應該也滿用功的,因為她跟我一樣,從沒缺課,
但我沒缺課是因為金魚眼。
只有一次因為ASUS颱風而補課的那次,或許是因為上午跟下午上一整天,
下午只上到一半她就回家了,我還目送她走下火車站前的捷運站 不過當然是跟蹤囉!

時間是Android英文的最後一堂課,
她不曾在下課時間站在那邊,今天不曉得為甚麼站在那邊好久好久Fonepad!
不知道在等誰?在做甚麼?只是在我眼睛注視的同時,
她卻向我點頭!?我卻當作甚麼也不知道地走了過去,我真沒種,
雖然點頭是最基本的禮貌,但是我們認識嗎?


不知道是我先發現的,還是正哥講了我才知道的?
正哥說,金魚眼是我國小同學,她說還不知道我會唸K中。

我回家翻了國小同學錄,找到了她的電話。

I: hello,我是英文班你的同學!喔!不是!應該說是你的國小同學Fonepad。
金魚眼: 喔喔,我知道啊!你杜洛唯啊!
I: 你還記得我聲音啊!?
金魚眼: 哈哈哈,怎麼會忘記!國小你常被我扁吧Padfone Infinity!
I: 喔喔,你大學考得怎樣啊?
金魚眼: 我喔,我想念外文!所以應該會去念政大,你呢?
I: 我也錄取了政大...

故事才剛剛開始呢...


恭喜!您已領取活動序號:A7XQAV4M Fonepad
恭喜!您已領取活動序號:P6328CRA

憑活動序號至7-ELEVEN ibon列印Fonepad兌換券,即可至全省Fonepad門市
兌換活動指定商品優惠換一項!
★ 買一送一(同系列商品任選)
(1) 德芙巧克力:香濃黑巧克力/絲滑牛奶/輕巧脆心/Padfone Infinity榛果葡萄
(2) 瑞穗雪糕:巧克力牛奶/草莓牛奶/鮮乳
(3) 萊萃美:綜合維生素100粒裝/葉黃素軟膠囊30粒裝
(4) 統一青草茶600ml/統一冬瓜茶600ml
(5) 浪味仙(蔬菜)
(6) 明治巧喜雪糕

★ ASUS買一送一Padfone Infinity(同品項)
(1) 國際牌Fonepad電池:3號(4入)/4號(4入)/1號(2入)

★ ASUS買一送一(同價位)
(1) 西莎蒸鮮包:成犬低脂雞肉/成犬低脂雞肉與蔬菜
(2) 偉嘉貓罐:ASUS沙丁魚特餐185g/海洋大餐185g


批次 機型 16G黑 16G白 32G黑 32G白 64G黑 64G白 可領貨時間 (3個工作天) 第一梯次 預約單號時間 (以1秒為單位) 2013/04/12/05 10:00:00 ~ 2013/04/12/05 10:09:58(含) 2013/04/12/05 10:00:00 ~ 2013/04/12/05 10:09:56(含) 2013/04/12/05 10:00:00 ~ 2013/04/12/05 10:09:46(含) 2013/04/12/05 10:00:00 ~ 2013/04/12/05 10:13:51(含) 2013/04/12/05 10:00:00 ~ 2013/04/12/05 10:21:58(含) 2013/04/12/05 10:00:00 ~ 2013/04/12/05 10:28:16(含) 2013/04/12/14 ~ 2013/04/12/18 第二梯次 預約單號時間 (以1秒為單位) 2013/04/12/05 10:09:59 ~ 2013/04/12/05 10:15:29(含) 2013/04/12/05 10:09:57 ~ 2013/04/12/05 10:15:22(含) 2013/04/12/05 10:09:47 ~ 2013/04/12/05 10:15:13(含) 2013/04/12/05 10:13:52 ~ 2013/04/12/05 10:24:13(含) 暫無供貨 暫無供貨 2013/04/12/17 ~ 2013/04/12/19 第三梯次 預約單號時間 (以1秒為單位) 2013/04-12-05 10:15:30 ~ 2013/04-12-05 10:18:19(含) 2013/04-12-05 10:15:23 ~ 2013/04-12-05 10:20:26(含) 2013/04-12-05 10:15:14 ~ 2013/04-12-05 10:19:03(含) 2013/04-12-05 10:24:14 ~ 2013/04-12-05 10:25:52(含) 2013/04-12-05 10:21:59 ~ 2013/04-12-05 10:29:45(含) 2013/04-12-05 10:28:17 ~ 2013/04-12-05 10:43:19(含) 2013/04/12/19 ~ 2013/04/12/21 第四梯次 預約單號時間 (以1秒為單位) 2013/04-12-05 10:18:20 ~ 2013/04-12-05 10:20:08(含) 2013/04-12-05 10:20:27 ~ 2013/04-12-05 10:23:21(含) 2013/04-12-05 10:19:04 ~ 2013/04-12-05 10:25:34(含) 2013/04-12-05 10:25:53 ~ 2013/04-12-05 10:31:27(含) 暫無供貨 暫無供貨 2013/04/12/21 ~ 2013/04/12/24 第五梯次 預約單號時間 (以1秒為單位) 2013/04-12-05 10:20:09 ~ 2013/04-12-05 10:40:21(含) 2013/04-12-05 10:23:22 ~ 2013/04-12-05 10:32:57(含) 2013/04-12-05 10:25:35 ~ 2013/04-12-05 10:27:16(含) 2013/04-12-05 10:31:28 ~ 2013/04-12-05 10:34:40(含) 2013/04-12-05 10:29:46 ~ 2013/04-12-05 10:38:57(含) 2013/04-12-05 10:43:20 ~ 2013/04-12-05 10:51:23(含) 2013/04/12/22 ~ 2013/04/12/25 第六梯次 預約單號時間 (以1秒為單位) 2013/04-12-05 10:40:22 ~ 2013/04-12-05 10:56:17(含) 2013/04-12-05 10:32:58 ~ 2013/04-12-05 10:52:24(含) 暫無供貨 2013/04-12-05 10:34:41 ~ 2013/04-12-05 10:37:44(含) 2013/04-12-05 10:38:58 ~ 2013/04-12-05 10:50:07(含) 2013/04-12-05 10:51:24 ~ 2013/04-12-05 11:01:14(含) 2013/04/12/24 ~ 2013/04/12/26 第七梯次 預約單號時間 (以1秒為單位) 2013/04-12-05 10:56:18 ~ 2013/04-12-05 11:26:00(含) 2013/04-12-05 10:52:25 ~ 2013/04-12-05 11:11:22(含) 暫無供貨 暫無供貨 暫無供貨 暫無供貨 2013/04/12/26 ~ 2013/04/12/28 第八梯次 預約單號時間 (以1秒為單位) 2013/04-12-05 11:26:01 ~ 2013/04-12-05 11:49:00(含) 2013/04-12-05 11:11:23 ~ 2013/04-12-05 11:53:01(含) 2013/04-12-05 10:27:17 ~ 2013/04-12-05 10:27:51(含) 2013/04-12-05 10:37:45 ~ 2013/04-12-05 10:39:06(含) 暫無供貨 暫無供貨 2013/04/12/28 ~ 2013/01/03

2013/4/12

GPU 的基本介紹

GPU 的硬體架構
 

這裡我們會簡單介紹,NVIDIA 目前支援 CUDA GPU,其在執行 CUDA 程式的部份(基本上就是其 shader 單元)的架構。這裡的資料是綜合 NVIDIA 所公布的資訊,以及 NVIDIA 在各個研討會、學校課程等所提供的資料,因此有可能會有不正確的地方。主要的資料來源包括 NVIDIA CUDA Programming Guide 1.1NVIDIA Supercomputing '07 介紹 CUDA session,以及 UIUC CUDA 課程。

GPU 的基本介紹

目前 NVIDIA 推出的顯示晶片,支援 CUDA 的是 G80 系列的顯示晶片。其中 G80 顯示晶片支援 CUDA 1.0 版,而 G84G86G92G94G96 則支援 CUDA 1.1 版。基本上,除了最早的 GeForce 8800 Ultra/GTX 320MB/640MB 版本的 GeForce 8800GTSTesla 等顯示卡是 CUDA 1.0 版之外,其它 GeForce 8 系列及 9 系列顯示卡都支援 CUDA 1.1。詳細情形可以參考 CUDA Programming Guide 1.1 Appendix A

所有目前支援 CUDA NVIDIA 顯示晶片,其 shader 部份都是由多個 multiprocessors 組成。每個 multiprocessor 裡包含了八個 stream processors,其組成是四個四個一組,也就是說實際上可以看成是有兩組 4D SIMD 處理器。此外,每個 multiprocessor 還具有 8192 個暫存器,16KB share memory,以及 texture cache constant cache。大致上如下圖所示:

詳細的 multiprocessor 資訊,都可以透過 CUDA  cudaGetDeviceProperties() 函式或 cuDeviceGetProperties() 函式取得。不過,目前還沒有辦法直接取得一個顯示晶片中有多少 multiprocessor 的資訊。

CUDA 中,大部份基本的運算動作,都可以由 stream processor 進行。每個 stream processor 都包含一個 FMAfused-multiply-add)單元,可以進行一個乘法和一個加法。比較複雜的運算則會需要比較長的時間。

執行過程

在執行 CUDA 程式的時候,每個 stream processor 就是對應一個 thread。每個 multiprocessor 則對應一個 block。從之前的文章中,可以注意到一個 block 經常有很多個 thread(例如 256 個),遠超過一個 multiprocessor 所有的 stream processor 數目。這又是怎麼回事呢?

實際上,雖然一個 multiprocessor 只有八個 stream processor,但是由於 stream processor 進行各種運算都有 latency,更不用提記憶體存取的 latency,因此 CUDA 在執行程式的時候,是以 warp 為單位。目前的 CUDA 裝置,一個 warp 裡面有 32 threads,分成兩組 16 threads half-warp。由於 stream processor 的運算至少有 4 cycles latency,因此對一個 4D stream processors 來說,一次至少執行 16 threads(即 half-warp)才能有效隱藏各種運算的 latency

由於 multiprocessor 中並沒有太多別的記憶體,因此每個 thread 的狀態都是直接保存在 multiprocessor 的暫存器中。所以,如果一個 multiprocessor 同時有愈多的 thread 要執行,就會需要愈多的暫存器空間。例如,假設一個 block 裡面有 256 threads,每個 thread 用到 20 個暫存器,那麼總共就需要 256x20 = 5,120 個暫存器才能保存每個 thread 的狀態。目前 CUDA 裝置中每個 multiprocessor 8,192 個暫存器,因此,如果每個 thread 使用到 16 個暫存器,那就表示一個 multiprocessor 同時最多只能維持 512 thread 的執行。如果同時進行的 thread 數目超過這個數字,那麼就會需要把一部份的資料儲存在顯示記憶體中,就會降低執行的效率了。

Shared memory

目前 CUDA 裝置中,每個 multiprocessor 16KB shared memoryShared memory 分成 16 bank。如果同時每個 thread 是存取不同的 bank,就不會產生任何問題,存取 shared memory 的速度和存取暫存器相同。不過,如果同時有兩個(或更多個) threads 存取同一個 bank 的資料,就會發生 bank conflict,這些 threads 就必須照順序去存取,而無法同時存取 shared memory 了。

Shared memory 是以 4 bytes 為單位分成 banks。因此,假設以下的資料:

    __shared__ int data[128];

那麼,data[0] bank 0data[1] bank 1data[2] bank 2data[15] bank 15,而 data[16] 又回到 bank 0。由於 warp 在執行時是以 half-warp 的方式執行,因此分屬於不同的 half warp threads,不會造成 bank conflict

因此,如果程式在存取 shared memory 的時候,使用以下的方式:

    int number = data[base + tid];

那就不會有任何 bank conflict,可以達到最高的效率。但是,如果是以下的方式:

    int number = data[base + 4 * tid];

那麼,thread 0 thread 4 就會存取到同一個 bankthread 1 thread 5 也是同樣,這樣就會造成 bank conflict。在這個例子中,一個 half warp 16 threads 會有四個 threads 存取同一個 bank,因此存取 share memory 的速度會變成原來的 1/4

一個重要的例外是,當多個 thread 存取到同一個 shared memory 的位址時,shared memory 可以將這個位址的 32 bits 資料「廣播」到所有讀取的 threads,因此不會造成 bank conflict。例如:

    int number = data[3];

這樣不會造成 bank conflict,因為所有的 thread 都讀取同一個位址的資料。

很多時候 shared memory bank conflict 可以透過修改資料存放的方式來解決。例如,以下的程式:

    data[tid] = global_data[tid];
    ...
    int number = data[16 * tid];

會造成嚴重的 bank conflict,為了避免這個問題,可以把資料的排列方式稍加修改,把存取方式改成:

    int row = tid / 16;
    int column = tid % 16;
    data[row * 17 + column] = global_data[tid];
    ...
    int number = data[17 * tid];

這樣就不會造成 bank conflict 了。

Global memory

由於 multiprocessor 並沒有對 global memory cache(如果每個 multiprocessor 都有自己的 global memory cache,將會需要 cache coherence protocol,會大幅增加 cache 的複雜度),所以 global memory 存取的 latency 非常的長。除此之外,前面的文章中也提到過 global memory 的存取,要儘可能的連續。這是因為 DRAM 存取的特性所造成的結果。

更精確的說,global memory 的存取,需要是 "coalesced"。所謂的 coalesced,是表示除了連續之外,而且它開始的位址,必須是每個 thread 所存取的大小的 16 倍。例如,如果每個 thread 都讀取 32 bits 的資料,那麼第一個 thread 讀取的位址,必須是 16*4 = 64 bytes 的倍數。

如果有一部份的 thread 沒有讀取記憶體,並不會影響到其它的 thread 速行 coalesced 的存取。例如:

    if(tid != 3) {
        int number = data[tid];
    }

雖然 thread 3 並沒有讀取資料,但是由於其它的 thread 仍符合 coalesced 的條件(假設 data 的位址是 64 bytes 的倍數),這樣的記憶體讀取仍會符合 coalesced 的條件。

在目前的 CUDA 1.1 裝置中,每個 thread 一次讀取的記憶體資料量,可以是 32 bits64 bits、或 128 bits。不過,32 bits 的效率是最好的。64 bits 的效率會稍差,而一次讀取 128 bits 的效率則比一次讀取 32 bits 要顯著來得低(但仍比 non-coalesced 的存取要好)。

如果每個 thread 一次存取的資料並不是 32 bits64 bits、或 128 bits,那就無法符合 coalesced 的條件。例如,以下的程式:

    struct vec3d { float x, y, z; };
    ...
    __global__ void func(struct vec3d* data, float* output)
    {
        output[tid] = data[tid].x * data[tid].x +
            data[tid].y * data[tid].y +
            data[tid].z * data[tid].z;
    }

並不是 coalesced 的讀取,因為 vec3d 的大小是 12 bytes,而非 4 bytes8 bytes、或 16 bytes。要解決這個問題,可以使用 __align(n)__ 的指示,例如:

    struct __align__(16) vec3d { float x, y, z; };

這會讓 compiler vec3d 後面加上一個空的 4 bytes,以補齊 16 bytes。另一個方法,是把資料結構轉換成三個連續的陣列,例如:

    __global__ void func(float* x, float* y, float* z, float* output)
    {
        output[tid] = x[tid] * x[tid] + y[tid] * y[tid] +
            z[tid] * z[tid];
    }

如果因為其它原因使資料結構無法這樣調整,也可以考慮利用 shared memory GPU 上做結構的調整。例如:

    __global__ void func(struct vec3d* data, float* output)
    {
        __shared__ float temp[THREAD_NUM * 3];
        const float* fdata = (float*) data;
        temp[tid] = fdata[tid];
        temp[tid + THREAD_NUM] = fdata[tid + THREAD_NUM];
        temp[tid + THREAD_NUM*2] = fdata[tid + THREAD_NUM*2];
        __syncthreads();
        output[tid] = temp[tid*3] * temp[tid*3] +
            temp[tid*3+1] * temp[tid*3+1] +
            temp[tid*3+2] * temp[tid*3+2];
    }

在上面的例子中,我們先用連續的方式,把資料從 global memory 讀到 shared memory。由於 shared memory 不需要擔心存取順序(但要注意 bank conflict 問題,參照前一節),所以可以避開 non-coalesced 讀取的問題。

Texture

CUDA 支援 texture。在 CUDA kernel 程式中,可以利用顯示晶片的 texture 單元,讀取 texture 的資料。使用 texture global memory 最大的差別在於 texture 只能讀取,不能寫入,而且顯示晶片上有一定大小的 texture cache。因此,讀取 texture 的時候,不需要符合 coalesced 的規則,也可以達到不錯的效率。此外,讀取 texture 時,也可以利用顯示晶片中的 texture filtering 功能(例如 bilinear filtering),也可以快速轉換資料型態,例如可以直接將 32 bits RGBA 的資料轉換成四個 32 bits 浮點數。

顯示晶片上的 texture cache 是針對一般繪圖應用所設計,因此它仍最適合有區塊性質的存取動作,而非隨機的存取。因此,同一個 warp 中的各個 thread 最好是讀取位址相近的資料,才能達到最高的效率。

對於已經能符合 coalesced 規則的資料,使用 global memory 通常會比使用 texture 要來得快。

運算單元

Stream processor 裡的運算單元,基本上是一個浮點數的 fused multiply-add 單元,也就是說它可以進行一次乘法和一次加法,如下所示:

    a = b * c + d;

compiler 會自動把適當的加法和乘法運算,結合成一個 fmad 指令。

除了浮點數的加法及乘法之外,整數的加法、位元運算、比較、取最小值、取最大值、及以型態的轉換(浮點數轉整數或整數轉浮點數)都是可以全速進行的。整數的乘法則無法全速進行,但 24 bits 的乘法則可以。在 CUDA 中可以利用內建的 __mul24 __umul24 函式來進行 24 bits 的整數乘法。

浮點數的除法是利用先取倒數,再相乘的方式計算,因此精確度並不能達到 IEEE 754 的規範(最大誤差為 2 ulp)。內建的 __fdividef(x,y) 提供更快速的除法,和一般的除法有相同的精確度,但是在 2216 < y < 2218 時會得到錯誤的結果。

此外 CUDA 還提供了一些精確度較低的內建函式,包括 __expf__logf__sinf__cosf__powf 等等。這些函式的速度較快,但精確度不如標準的函式。詳細的資料可以參考 CUDA Programming Guide 1.1 Appendix B

和主記憶體間的資料傳輸

CUDA 中,GPU 不能直接存取主記憶體,只能存取顯示卡上的顯示記憶體。因此,會需要將資料從主記憶體先複製到顯示記憶體中,進行運算後,再將結果從顯示記憶體中複製到主記憶體中。這些複製的動作會限於 PCI Express 的速度。使用 PCI Express x16 時,PCI Express 1.0 可以提供雙向各 4GB/s 的頻寬,而 PCI Express 2.0 則可提供 8GB/s 的頻寬。當然這都是理論值。

從一般的記憶體複製資料到顯示記憶體的時候,由於一般的記憶體可能隨時會被作業系統搬動,因此 CUDA 會先將資料複製到一塊內部的記憶體中,才能利用 DMA 將資料複製到顯示記憶體中。如果想要避免這個重複的複製動作,可以使用 cudaMallocHost 函式,在主記憶體中取得一塊 page locked 的記憶體。不過,如果要求太大量的 page locked 的記憶體,將會影響到作業系統對記憶體的管理,可能會減低系統的效率。