• 【一天一点.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:

  • 相关阅读:
    linux 内存检测工具 kfence 详解(二)
    双11预售在即,小红书品牌如何高效分析竞品?
    【左神算法笔记】Class2,3 各种排序算法总结
    [ C++ ] 抽象类 虚函数 虚函数表 -- C++多态(1)
    好用的开源项目地址
    38-数组 _ 一维数组
    【python3】5.正则表达式
    【JS】获取当前时间的简便方法
    深入MNN:开源深度学习框架的介绍、安装与编译指南
    【学习日记】win64配置openni的vs2022编译环境
  • 原文地址:https://www.cnblogs.com/VAllen/p/18293030/accelerate-summation-calculations-using-vector