C#并行计算(SIMD)应用

复制代码
using System.Numerics;

namespace SIMDDemo
{
    internal class Program
    {
        /* 
        实战案例:200万数据点的统计计算
        场景描述
        - 数据量:200万个float类型的测量点
        - 计算需求:最大值、最小值、平均值
        - 性能要求:毫秒级响应,支持生产线实时检测

        SIMD向量化处理:
        使用System.Numerics.Vector<T>实现单指令多数据流处理,一次性处理多个数据点(取决于硬件,通常是4或8个float),大幅减少循环迭代次数
         * 
        */
        static void Main(string[] args)
        {
            // 生成测试数据 (200万个随机float值)
            int createCount = 16;//2000000
            Console.WriteLine("\r\n生成测试数据");
            float[] data = new float[createCount];
            Random rand = new Random();

            for (int i = 0; i < data.Length; i++)
            {
                data[i] = (float)(rand.NextDouble() * 1000);
            }

            Console.WriteLine(string.Join("\r\n", data));

            // 计算统计量并测量时间
            var stopwatch = System.Diagnostics.Stopwatch.StartNew();

            CalculateStatistics(
                data,
                out float min,
                out float max,
                out float mean
            );

            stopwatch.Stop();

            Console.WriteLine("\r\n输出结果");
            Console.WriteLine($"数据量: {data.Length:N0}");
            Console.WriteLine($"最小值: {min:F4}");
            Console.WriteLine($"最大值: {max:F4}");
            Console.WriteLine($"平均值: {mean:F4}");
            Console.WriteLine($"计算耗时: {stopwatch.ElapsedMilliseconds} ms");
        }

        static void CalculateStatistics(float[] data, out float min, out float max, out float mean)
        {
            int length = data.Length;
            int vectorSize = Vector<float>.Count;// 向量大小:8
            int i = 0;

            // 初始化SIMD向量
            var vMin = new Vector<float>(float.MaxValue);
            var vMax = new Vector<float>(float.MinValue);
            var vSum = Vector<float>.Zero;

            // 处理向量化部分(SIMD)
            for (; i <= length - vectorSize; i += vectorSize)
            {
                var vData = new Vector<float>(data, i);// 单指令多数据流处理 <594.0291, 805.2193, 795.9451, 39.850945, 715.462, 330.4536, 281.41626, 497.84033>

                vMin = Vector.Min(vMin, vData);
                vMax = Vector.Max(vMax, vData);
                vSum += vData;
            }

            // 提取向量化结果
            min = ExtractMin(vMin);
            max = ExtractMax(vMax);
            float sum = ExtractSum(vSum);

            // 处理剩余的非向量化数据
            for (; i < length; i++)
            {
                float value = data[i];

                min = Math.Min(min, value);
                max = Math.Max(max, value);
                sum += value;
            }

            mean = sum / length; // 计算平均值
        }

        static float ExtractMin(Vector<float> vector)
        {
            float min = float.MaxValue;
            for (int i = 0; i < Vector<float>.Count; i++)
            {
                min = Math.Min(min, vector[i]);
            }
            return min;
        }

        static float ExtractMax(Vector<float> vector)
        {
            float max = float.MinValue;
            for (int i = 0; i < Vector<float>.Count; i++)
            {
                max = Math.Max(max, vector[i]);
            }
            return max;
        }

        private static float ExtractSum(Vector<float> vector)
        {
            float sum = 0;
            for (int i = 0; i < Vector<float>.Count; i++)
            {
                sum += vector[i];
            }
            return sum;
        }
    }
}