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