最近一直在想,C++中有CUDA硬鞍,但是寫(xiě)代碼有時(shí)候會(huì)覺(jué)得過(guò)于麻煩贰镣,再加上筆者經(jīng)常在一個(gè)三維設(shè)計(jì)軟件Rhinoceros上做網(wǎng)格算法開(kāi)發(fā)呜象,C#相較于C++顯得更為友好。因此筆者就在尋找支持C#的GPU加速庫(kù)碑隆,結(jié)果最終找到了AleaGPU恭陡,這個(gè)庫(kù)看上去已經(jīng)做的非常完善了,基于.Net上煤,安裝配置十分方便休玩,并且也支持CUDA編程。因此我就打算寫(xiě)本系列筆記記錄自己的學(xué)習(xí)過(guò)程劫狠。
Alea GPU簡(jiǎn)介
這里直接Google翻譯簡(jiǎn)介部分了:
使用Alea GPU拴疤,您可以利用這種處理能力在Windows,Linux和Mac OS X上以簡(jiǎn)單有效的方式來(lái)加速.NET和Mono應(yīng)用程序独泞。您可以使用.NET語(yǔ)言和已知工具來(lái)開(kāi)發(fā)GPU代碼呐矾。Alea GPU運(yùn)行時(shí)系統(tǒng)可有效處理GPU上的執(zhí)行以及所有內(nèi)存管理。
簡(jiǎn)單來(lái)說(shuō)Alea GPU的關(guān)鍵字是: 高效懦砂、易學(xué)蜒犯、快速、跨平臺(tái)
具體來(lái)說(shuō):
- 跨平臺(tái):無(wú)論是Windows, Linux和Mac OS X上都能用荞膘。
- 具有自動(dòng)化內(nèi)存管理的功能:這對(duì)于GPU編程初學(xué)者較友好
- 支持CUDA生態(tài):也就是說(shuō)那些cuBlas罚随,cuRand和cuDNN在Alea GPU里都能用
- 安裝簡(jiǎn)單:不必多說(shuō)了,NuGet軟件包一鍵安裝
- 統(tǒng)一了CPU和GPU類(lèi)型:.NET數(shù)組和許多.NET類(lèi)型可以直接在GPU代碼中使用羽资,包括諸如數(shù)組長(zhǎng)度之類(lèi)的屬性
- 高性能:速度與CUDA C/C++一樣快
- 文檔和示例豐富(不過(guò)就筆者目前來(lái)看淘菩,這一點(diǎn)必須吐槽,因?yàn)楣倬W(wǎng)上的文檔資料并不多屠升,其他論壇上幾乎沒(méi)有資料潮改,stack overflow上也只有寥寥幾個(gè)相關(guān)問(wèn)題)
想看更多深入了解Alea GPU可以直接訪問(wèn)Alea GPU。
兩種編程模型
Parallel-For and Parallel Aggregation
Alea GPU Parallel-For可以對(duì)集合中的每個(gè)元素或有序區(qū)間的每個(gè)索引并行地執(zhí)行l(wèi)ambda表達(dá)式腹暖、委托或在GPU上執(zhí)行的函數(shù)汇在。Alea GPU Parallel Aggregation是用于借助二進(jìn)制函數(shù),委托或lambda表達(dá)式將多個(gè)輸入聚合為最終值微服。結(jié)合Alea GPU自動(dòng)化內(nèi)存管理趾疚,開(kāi)發(fā)人員可以編寫(xiě)并行GPU代碼,就像編寫(xiě)串行循環(huán)一樣以蕴。
說(shuō)白了糙麦,這是為沒(méi)有接觸過(guò)GPU編程的用戶(hù)設(shè)計(jì)的,用戶(hù)可以像使用CPU上的并行Parallel.For()一樣來(lái)使用Gpu.For()來(lái)實(shí)現(xiàn)GPU并行丛肮,需要注意的是赡磅,GPU上的并行傳入傳出只能為數(shù)組和指針。
CUDA
為了獲得最大的靈活性宝与,Alea GPU還提供了CUDA編程模型焚廊。它旨在通過(guò)大量線程執(zhí)行數(shù)據(jù)并行工作負(fù)載冶匹。CUDA 向程序員提出了諸如線程(Threads),線程塊(Thread Blocks)或網(wǎng)格(Grid)之類(lèi)的并行概念咆瘟,以便用靈活而抽象的方式將并行計(jì)算映射到GPU線程嚼隘。CUDA還向程序員給出了GPU內(nèi)存層次結(jié)構(gòu)。他可以利用不同的內(nèi)存類(lèi)型來(lái)優(yōu)化內(nèi)存訪問(wèn)和IO帶寬袒餐。
通過(guò)筆者近期一個(gè)月的使用體驗(yàn)來(lái)看飞蛹,一部分的CUDA功能已經(jīng)被移植到Alea GPU,但是仍有一小部分功能沒(méi)有灸眼,比如僅在設(shè)備端拷貝一個(gè)數(shù)組中的某一個(gè)元素卧檐,這在Alea GPU中沒(méi)有提供對(duì)應(yīng)的方法,它只能一次拷貝出所有的數(shù)據(jù)焰宣,由于對(duì)于GPU編程而言霉囚,當(dāng)數(shù)據(jù)量足夠大時(shí),計(jì)算所花費(fèi)的時(shí)間要小于Device與Host之間的傳輸速度匕积,因此這一點(diǎn)會(huì)非常影響程序的效率盈罐。
注意事項(xiàng):
- 在CUDA中我們稱(chēng)GPU為Device,稱(chēng)CPU為Host闸天,以此來(lái)強(qiáng)調(diào)一個(gè)事實(shí)暖呕,即 GPU 是一個(gè)物理上獨(dú)立的設(shè)備斜做,是主機(jī)的一個(gè)協(xié)同處理器苞氮。
- Alea GPU不支持CUDA 9.0以上版本
關(guān)于CUDA GPU編程的相關(guān)知識(shí)可以看我之前的筆記:CUDA筆記
安裝Alea
Alea的安裝配置非常方便,只需要右鍵單擊引用->管理NuGet程序包瓤逼,在瀏覽里搜索Alea笼吟,點(diǎn)擊安裝即可。
不過(guò)需要注意的是霸旗,由于AleaGPU是F#寫(xiě)的贷帮,因此還需要安裝一個(gè)FSharp.Core,同樣在NuGet包管理那里搜索FSharp.Core安裝即可诱告。
第一個(gè)案例文件
從官網(wǎng)上下載下來(lái)了第一個(gè)案例文件撵枢,這段代碼是用來(lái)反饋gpu設(shè)備信息的
using System;
using System.Linq;
using Alea;
namespace DeviceQuery
{
class Program
{
static void Main()
{
var devices = Device.Devices;
var numGpus = devices.Length;
foreach (var device in devices)
{
device.Print();
// note that device ids for all GPU devices in a system does not need to be continuous
var id = device.Id;
var arch = device.Arch;
var numMultiProc = device.Attributes.MultiprocessorCount;
}
// all device ids
var deviceIds = devices.Select(device => device.Id);
Console.ReadKey();
}
}
}