复制代码
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;
}
}
}