.net core SIMD范例分析

发布于 2019-08-25  294 次阅读


单指令多数据流(SIMD)是CPU基本运算之外为了提高并行处理多条数据效率的技术,常用于多媒体处理如视频,3D模拟的计算。实现方式不同品牌的CPU各有自己的指令集,如SSE MMX 3DNOW等。

C#开发.net core软件的过程中也可以让编译器自动采用这些SIMD指令集进行代码优化,测试了一下在我的AMD 锐龙7 2700X上对于整数加法处理可以提高10倍的效率。

下面是我自己写的例子:

using System; using System.Collections.Generic; using System.Linq; using System.Numerics; using System.Diagnostics; using System.Text; using System.Threading.Tasks; namespace MySIMDTest { class Program { static Random rand = new Random(); static Vector<int> getVec32(int count) { var lst = new List<int>(count); for (int i = 0; i < count; ++i) lst.Add(rand.Next(100)); return new Vector<int>(lst.ToArray()); } static Vector<short> getVec16(int count) { var lst = new List<int>(count); for (int i = 0; i < count; ++i) lst.Add(rand.Next(100)); return new Vector<short>(lst.Select(i => (short)i).ToArray()); } static void Main(string[] args) { var sw = new Stopwatch(); var testTimes = (int)(Math.Pow(10, 5)); var vecSize = (int)(Math.Pow(10, 2)); Action testNormal = () => { Console.Write("normal test "); var lstVecN1 = new List<Vector<int>>(); var lstVecN2 = new List<Vector<int>>(); for (int i = 0; i < testTimes; ++i) { lstVecN1.Add(getVec32(vecSize)); lstVecN2.Add(getVec32(vecSize)); } sw.Restart(); for (int i = 0; i < testTimes; ++i) { for(int j = 0; j < vecSize; ++j) { var r = lstVecN1[i] + lstVecN2[i]; } } sw.Stop(); Console.WriteLine(sw.Elapsed); }; Action test16 = () => { Console.Write("16 test"); var lstVecA1 = new List<Vector<short>>(); var lstVecA2 = new List<Vector<short>>(); for (int i = 0; i < testTimes; ++i) { lstVecA1.Add(getVec16(vecSize)); lstVecA2.Add(getVec16(vecSize)); } sw.Restart(); for (int i = 0; i < testTimes; ++i) { var result1 = lstVecA1[i] + lstVecA2[i]; } sw.Stop(); Console.WriteLine(sw.Elapsed); }; Action test32 = () => { Console.Write("32 test"); var lstVecB1 = new List<Vector<int>>(); var lstVecB2 = new List<Vector<int>>(); for (int i = 0; i < testTimes; ++i) { lstVecB1.Add(getVec32(vecSize)); lstVecB2.Add(getVec32(vecSize)); } sw.Restart(); for (int i = 0; i < testTimes; ++i) { var result1 = lstVecB1[i] + lstVecB2[i]; } sw.Stop(); Console.WriteLine(sw.Elapsed); }; for (int i = 0; i < 8; ++i) testNormal(); for (int i = 0; i < 8; ++i) test32(); for (int i = 0; i < 8; ++i) test16(); Console.ReadKey(); } } }

运行结果:

只要用Vector<T>支持的重载运算符来代替数组或者列表之类进行计算,即可获得编译器SIMD自动优化指令的效果。不过目前文档里说只支持x86系列的CPU ARM的CPU相关支持还在研发中



点击数:183


一沙一世界,一花一天堂。君掌盛无边,刹那成永恒。