如何优化欧氏距离计算?矩阵点距离计算提速方法咨询
优化矩阵欧氏距离计算效率的方案
针对你这段遍历10000×10000矩阵计算欧氏距离的代码,以下是几个直接有效的优化方向:
预分配List容量,避免频繁扩容
原代码中List默认初始容量很小,每次Add操作超过当前容量时,都会触发数组扩容(通常是翻倍)并复制现有元素,1亿量级的元素会导致多次扩容,开销极大。可以先统计非't'元素的数量,直接初始化对应容量的List:// 先统计非't'元素总数 int nonTCount = 0; for (int i = 0; i < 10000; i++) { for (int r = 0; r < 10000; r++) { if (fields[i, r] != 't') nonTCount++; } } // 初始化对应容量的List,避免后续扩容 List<Tuple<int, int, double>> tuples = new List<Tuple<int, int, double>>(nonTCount);如果不想额外遍历统计,也可以直接设置初始容量为
10000*10000,彻底避免扩容操作。替换Math.Pow为整数乘法,削减浮点运算开销
Math.Pow是通用幂运算函数,针对整数平方场景,直接用(i-x)*(i-x)替代Math.Pow(i-x,2),能避免不必要的浮点转换和通用计算逻辑,速度提升明显:int dx = i - x; int dy = r - y; double distance = Math.Sqrt(dx * dx + dy * dy);用自定义结构体替代Tuple,降低对象创建开销
Tuple虽然是值类型,但每次Tuple.Create仍有一定的初始化开销。自定义结构体更轻量,字段语义也更清晰:// 自定义结构体存储点坐标和距离 public struct PointWithDistance { public int Row; public int Col; public double Distance; public PointWithDistance(int row, int col, double distance) { Row = row; Col = col; Distance = distance; } } // 使用时直接实例化结构体 List<PointWithDistance> distances = new List<PointWithDistance>(nonTCount); distances.Add(new PointWithDistance(i, r, distance));并行化循环,利用多核CPU资源
每个点的距离计算完全独立,没有依赖关系,可以用Parallel.For并行处理行遍历,充分利用多核CPU。注意List不是线程安全的,推荐每个线程维护独立子列表,最后合并:int coreCount = Environment.ProcessorCount; List<PointWithDistance>[] threadLists = new List<PointWithDistance>[coreCount]; for (int t = 0; t < coreCount; t++) { threadLists[t] = new List<PointWithDistance>(); } Parallel.For(0, 10000, i => { // 分配当前线程对应的子列表 int threadIndex = Thread.CurrentThread.ManagedThreadId % coreCount; var subList = threadLists[threadIndex]; for (int r = 0; r < 10000; r++) { if (fields[i, r] != 't') { int dx = i - x; int dy = r - y; double distance = Math.Sqrt(dx * dx + dy * dy); subList.Add(new PointWithDistance(i, r, distance)); } } }); // 合并所有子列表 List<PointWithDistance> finalList = new List<PointWithDistance>(nonTCount); foreach (var list in threadLists) { finalList.AddRange(list); }省略开根号(业务允许的情况下)
如果后续只需要比较距离远近,不需要精确的欧氏距离值,可以直接存储平方距离(dx*dx + dy*dy),完全省去Math.Sqrt的浮点运算开销,这是最显著的优化之一:public struct PointWithSquaredDistance { public int Row; public int Col; public long SquaredDistance; public PointWithSquaredDistance(int row, int col, long squaredDistance) { Row = row; Col = col; SquaredDistance = squaredDistance; } } // 计算时直接用整数运算,避免浮点转换 long squaredDist = (long)dx * dx + (long)dy * dy;
内容的提问来源于stack exchange,提问作者Sneikso34
相关产品推荐
相关产品推荐

