您的位置:首頁 > 教學(xué)課堂 > .NET技術(shù)
來源:長(zhǎng)沙北大青鳥大計(jì)校區(qū)|發(fā)布時(shí)間:2015-08-06 11:51:41
SIMD
Mono團(tuán)隊(duì)一直以他們對(duì)SIMD,即單指令流多數(shù)據(jù)流特性的支持引以為傲。SIMD是一種CPU指令集,它能夠在同一時(shí)間對(duì)最多8個(gè)值進(jìn)行同一操作。而隨著.NET CLR版本4.6的推出,Windows開發(fā)者終于也能夠使用這一特性了。
為了實(shí)際觀察一下SIMD的效果,可以參考一下這個(gè)示例。假設(shè)你需要通過c[i] = a[i] + b[i]這種形式對(duì)兩個(gè)數(shù)組進(jìn)行相加,以得到第三個(gè)數(shù)組。通過使用SIMD,你可以按照以下方式編寫代碼:
for (int i = 0; i < size; i += Vector.Count) { Vectorv = new Vector(A,i) + new Vector(B,i); v.CopyTo(C,i); }
請(qǐng)注意這個(gè)循環(huán)是如何按Vector<int>.Count的取值進(jìn)行遞增的,根據(jù)CPU類型的不同,它的取值可能是4或是8。.NET JIT編譯器將根據(jù)CPU的不同生成相應(yīng)的代碼,以4或8的值對(duì)數(shù)組進(jìn)行批量相加。
這種方式看起來有些繁瑣,因此微軟還提供了一系列輔助類,包括:
Matrix3x2 結(jié)構(gòu)
Matrix4x4結(jié)構(gòu)
Plane結(jié)構(gòu)
Quaternion結(jié)構(gòu)
Vector 類
Vector(T) 結(jié)構(gòu)
Vector2結(jié)構(gòu)
Vector3結(jié)構(gòu)
Vector4結(jié)構(gòu)
恐怕大多數(shù)開發(fā)者都不知道這一點(diǎn):.NET經(jīng)常會(huì)對(duì)同一個(gè)程序集加載兩次。發(fā)生這種情況的條件是.NET首先加載了某個(gè)程序集的IL版本,隨后又加載了同一程序集的NGEN版本(即預(yù)編譯版本)。這種方式對(duì)于物理內(nèi)存來說是相當(dāng)嚴(yán)重的浪費(fèi),尤其是對(duì)諸如Visual Studio這樣的大型32位應(yīng)用程序來說更為明顯。
而在.NET 4.6中,一旦CLR加載了某個(gè)程序集的NGEN版本,它會(huì)自動(dòng)清空對(duì)應(yīng)的IL版本所占用的內(nèi)存。
早先我們?cè)懻撨^.NET 4.0中所引入的垃圾回收滯后時(shí)間模式,雖然這種方式比起讓GC完全停止一段時(shí)間的做法要可靠許多,但對(duì)于許多GC場(chǎng)景來說,這種方式仍算不上完整。
在.NET 4.6中,你將能夠通過一種更精密的方式臨時(shí)中止垃圾回收器的運(yùn)作,新的TryStartNoGCRegion方法允許你指定在小對(duì)象以及大對(duì)象的堆中需要多少內(nèi)存。
如果出現(xiàn)內(nèi)存不足的情況,運(yùn)行時(shí)將會(huì)返回false,或是停止運(yùn)行,直到通過GC清理得到足夠的內(nèi)存為止。你可以通過為TryStartNoGCRegion傳入某個(gè)標(biāo)記的方式控制這一行為,如果你成功地進(jìn)入了某個(gè)無GC區(qū)域(在過程結(jié)束前不允許進(jìn)行GC),那么在過程結(jié)束時(shí)必須調(diào)用EndNoGCRegion方法。
在官方文檔中并沒有說明該方法是否是線程安全的,不過考慮到GC的工作原理,你應(yīng)當(dāng)盡量避免讓兩個(gè)進(jìn)程同時(shí)嘗試改變GC狀態(tài)的做法。
對(duì)于GC的另一項(xiàng)改進(jìn)是它處理pinned對(duì)象(即一旦分配后不可移動(dòng)位置的對(duì)象)的方式。雖然在文檔中對(duì)此方面的描述有些語焉不詳,但當(dāng)你固定了某個(gè)對(duì)象的位置時(shí),通常也會(huì)固定其相鄰對(duì)象的位置。Rich Lander在文中寫道:
GC將以一種更優(yōu)化的方式處理pinned對(duì)象,因此GC能夠?qū)inned對(duì)象周圍的內(nèi)存進(jìn)行更有效地壓縮。對(duì)于大量使用pin方式的大規(guī)模應(yīng)用來說,這一改動(dòng)將極大地改進(jìn)應(yīng)用的性能。
GC對(duì)于如何使用較早的幾代中的內(nèi)存方面也體現(xiàn)出更好的智能性,Rich繼續(xù)寫道:
第1代對(duì)象升級(jí)為第2代對(duì)象的方式也得到了改進(jìn),以更有效地使用內(nèi)存。在為某一代分配新的內(nèi)存空間之前,GC會(huì)先嘗試使用可用的空間。同時(shí),在利用可用空間區(qū)域創(chuàng)建對(duì)象時(shí)使用了新的算法,使新分配的空間大小比起從前更接近于對(duì)象的大小。
最后一項(xiàng)改進(jìn)與性能并沒有直接的關(guān)系,但通過有效的利用仍然能達(dá)到優(yōu)化的效果。在異步API還沒有流行起來的年代,開發(fā)者可以利用線程本地存儲(chǔ)(TLS)緩存信息。TLS對(duì)于某個(gè)特定的線程來說就像是一種全局對(duì)象,這意味著你可以直接訪問上下文信息并進(jìn)行緩存,而無需顯式地傳遞某種上下文對(duì)象。
而在async/await模式中,線程本地存儲(chǔ)就變得毫無用武之地了。因?yàn)槊看握{(diào)用await的時(shí)候,都有可能跳轉(zhuǎn)至另一個(gè)線程。而且即便僥幸避開了這種情況,但其它代碼也有可能跳轉(zhuǎn)到你的線程中并干擾TLS中的信息。
新版本的.NET引入了異步本地存儲(chǔ)(ALS)機(jī)制以解決這一問題,ALS在語義上等價(jià)于線程本地存儲(chǔ),但它能夠隨著await的調(diào)用進(jìn)行相應(yīng)的跳轉(zhuǎn)。這一功能將通過AsyncLocal泛型類實(shí)現(xiàn),其內(nèi)部將調(diào)用CallContext對(duì)象用于保存數(shù)據(jù)。
全程面授,不高薪都難
申請(qǐng)成功后,我們將在24小時(shí)內(nèi)與您聯(lián)系
招生熱線: 4008-0731-86 / 0731-82186801
學(xué)校地址: 長(zhǎng)沙市天心區(qū)團(tuán)結(jié)路6號(hào)
Copyright © 2006 | 湖南大計(jì)信息科技有限公司 版權(quán)所有
湘ICP備14017520號(hào)-3