Vector(向量)是一種序列式容器,事實上和數組差很少,但它比數組更優越。通常來講數組不能動態拓展,所以在程序運行的時候不是浪費內存,就是形成越界。而Vector恰好彌補了這個缺陷,它的特徵是至關於可分配拓展的數組(動態數組),它的隨機訪問快,在中間插入和刪除慢,但在末端插入和刪除快。git
SIMD是Single Instruction Multiple Data的縮寫,一般中文譯爲單指令多數據流,通俗來說的話是:對多個數據執行同一個CPU指令,以達到平行運算的目的.github
在GPU以前咱們會經過CPU來運行該項技術來增長圖片的運算速度,例如Intel的MMX、SSE、SSE二、AVX,AMD的3DNow!等等,都是來使用SIMD
爲基礎的概念,在GPU技術日新月異的今天,CPU的SIMD技術不多用在了圖片運算方面了,更多的是在資料庫或者其餘用途上。算法
它適用於機器學習、加密算法、數據庫、和內容處理(視頻、圖像、音頻編碼)中,是多線程不錯的選擇。數據庫
SIMD能夠在多條數據通道中應用相同的操做,顯著的來提升CPU性能,一般,通道越多,性能越高(只要代碼符合處理器的指令集)api
Vector和Vector<T>
類爲咱們提供了SIMD(單指令,多數據)指令集(SSE,AVX)的調用方式,可讓咱們像在C/C++中同樣去調用內在函數,來直接操做大多數的SIMD指令了數組
Vector<T>
能夠爲任何的數字類型(sbyte, byte, short, ushort, int, uint, long, ulong, float, double),參考MSDocs多線程
另外咱們在System.Runtime.Intrinsics
可享受與平臺無關的功能,也就是咱們不用花費時間在不一樣平臺的兼容方面。機器學習
順便再說一下System.Runtime.Intrinsics.X86
在這個命名空間下,提供了SSE,SSE2,SSE3,SSSE3,SSE4.1,SSE4.2,AVX,AVX2,FMA,LZCNT,POPCNT,BMI1,BMI2,PCLMULQDQ和AES的不一樣Intel ISA的類的指令集。例如:在Avx類中提供了許多靜態方法,而每一個AVX方法都映射到了AVX的指令
,可是在這裏有一點咱們須要注意的是在這須要去經過IsSupported
去檢查硬件是否支持該功能。函數
在這以前咱們能夠經過Vector.IsHardwareAccelerated
來判斷硬件是否支持SIMD。性能
if (Vector.IsHardwareAccelerated == false) { //fallback to some other code; return; }
//建立Vector 重複相同的值 double[] doubArray = new double[] { 1, 2, 3, 4, 4, 3, 2, 1, -1, -2, -3, -4, -5 }; Span<double> douSpan = new Span<double>(doubArray, 8, 4); Vector<double> douZero = Vector<double>.Zero;//<0, 0, 0, 0> Vector<float> flOne = Vector<float>.One;//<1, 1, 1, 1, 0, 0, 0, 0> Vector<ushort> shAny = new Vector<ushort>(20);//<20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, 0, 0, 0> Vector<double> douV = new Vector<double>(doubArray); //Will contain <1, 2, 3, 4> Vector<double> spanduoV = new Vector<double>(douSpan); //Will contain <-1, -2, -3, -4> Vector<double> dou2V = new Vector<double>(doubArray, 5); //Will contain <3, 2, 1, -1> Vector<double> sumV = douV + dou2V; //Will contain <4, 4, 4, 3>
在具備AVX/AVX2功能的系統中,以上指令將建立包含4個重複的double,8個重複的float和16個重複的ushort的向量。
另外Vector能夠經過數組和Span
.NET中最原始的SIMD加速類型是Vector二、Vector3和Vector4類型,它們用二、3和4個單個值表示向量。下面的例子使用Vector2來添加兩個向量。
var v1 = new Vector2(0.1f, 0.2f); var v2 = new Vector2(1.1f, 2.2f); var vResult = v1 + v2;//1.2 2.4
可使用.NET向量計算載體如其餘數學性質Dot product,Transform,Clamp等等。
var v1 = new Vector2(0.1f, 0.2f); var v2 = new Vector2(1.1f, 2.2f); var vResult1 = Vector2.Dot(v1, v2); //0.55 var vResult2 = Vector2.Distance(v1, v2); //2.236068 var vResult3 = Vector2.Clamp(v1, Vector2.Zero, Vector2.One);//0.1 0.2
Vector<T>
可使用更長的向量。 Vector<T>
實例的計數是固定的,可是其值Vector<T>.Count
取決於運行代碼的計算機的CPU。
下面的示例演示使用Vector<T>
添加長數組元素。
double[] SimdVectorProd(double[] left, double[] right) { var offset = Vector<double>.Count; double[] result = new double[left.Length]; int i = 0; for (i = 0; i < left.Length; i += offset) { var v1 = new Vector<double>(left, i); var v2 = new Vector<double>(right, i); (v1 * v2).CopyTo(result, i); } //remaining items for (; i < left.Length; ++i) { result[i] = left[i] * right[i]; } return result; }