• 【一天一点.NET小知识】运用向量Vector<T>加速求和计算


    随着 .NET 版本的演进,从 .NET Standard 2.0 版本开始,支持 Vector 类型。
    .NET 8.0 版本开始,大量在 Runtime 提供的各个组件中运用向量计算,​特别是 Linq。
    Vector 类型:表示指定数值类型(适用于并行算法的低级别优化)的单个向量。

    假如我们有一个求和函数接受一个int数组入参,当它的长度大于等于8及其倍数以上时,那么我们就可以考虑使用向量Vector加速求和计算。

    以下是使用了向量的求和函数代码:

    internal class Program
    {
        static void Main(string[] args)
        {
            int[] array = Enumerable.Range(1, 32).ToArray();
            int result = Sum(array);
            Console.WriteLine(result);
            Console.ReadKey();
        }
    
        public static int Sum(int[] numbers)
        {
            ReadOnlySpan<int> span = new ReadOnlySpan<int>(numbers);
            ref int ptr = ref MemoryMarshal.GetReference(span);
            int result = 0;
            int vectorSize = Vector<int>.Count;
            int index;
            int remainder = span.Length % vectorSize;
            int vectorLength = span.Length - remainder;
            Vector<int> vector = Vector<int>.Zero;
            for (index = 0; index < vectorLength; index += vectorSize)
            {
                //Vector vector2 = new Vector(span.Slice(index, vectorSize));
                ref byte address = ref Unsafe.As<int, byte>(ref Unsafe.Add(ref Unsafe.AsRef(in ptr), index));
                Vector<int> vector2 = Unsafe.ReadUnalignedint>>(ref address);
                vector += vector2;
            }
    
            result += Vector.Dot<int>(vector, Vector<int>.One);
            for (; index < span.Length; index++)
            {
                result += Unsafe.Add(ref ptr, index);
            }
    
            return result;
        }
    }
    

    以下是相减函数代码:

    static int Sub(int[] numbers)
    {
    	ReadOnlySpan<int> span = new ReadOnlySpan<int>(numbers);
    	ref int ptr = ref MemoryMarshal.GetReference(span);
    	int result = 0;
    	int vectorSize = Vector<int>.Count;
    	int index;
    	int remainder = span.Length % vectorSize;
    	int vectorLength = span.Length - remainder;
    	for (index = 0; index < vectorLength; index += vectorSize)
    	{
    		ref byte address = ref Unsafe.As<int, byte>(ref Unsafe.Add(ref Unsafe.AsRef(in ptr), index));
    		Vector<int> vector = Unsafe.ReadUnalignedint>>(ref address);
    		result -= Vector.Dot<int>(vector, Vector<int>.One);
    	}
    
    	for (; index < span.Length; index++)
    	{
    		result -= Unsafe.Add(ref ptr, index);
    	}
    
    	return result + 2;
    }
    

    其它运算,例如相减,也是同理。
    以上代码,均可以在 .NET Standard 2.0 及以上版本运行。

    当我们向量 Vector 之后,特别是在一些频繁调用计算的场景,将获得指数量级的性能提升。
    需要注意的是,向量 Vector 依赖 CPU 硬件的 SIMD 指令集支持,在一些相对较旧的 古董CPU,可能不支持。

    PS:

  • 相关阅读:
    【小沐学Python】网络爬虫之urllib
    【第十四篇】商城系统-异步处理利器-CompletableFuture
    vue3+antd项目实战(后台管理系统)中菜单栏的实现(一)v-for循环 轻松实现多级菜单
    为什么很多新型编程语言都抛弃了 C 语言风格的 for 语句?
    杏仁损伤检测器——基于CNN的图像分类
    解决Navicat中文注释乱码问题
    QCustomPlot 坐标轴间隔显示刻度标签
    第三次CCF计算机软件能力认证
    Ae 动态图形模板
    Springboot——拦截器
  • 原文地址:https://www.cnblogs.com/VAllen/p/18293030/accelerate-summation-calculations-using-vector