• C# 计算两两坐标之间的距离(SIMD加速)


    问题描述:对于Point[] points坐标数组(Point是坐标点,包含X与Y),请计算两两坐标点之间的距离。

    思路:既然是算距离,没有别的要求,只需要最简单的曼哈顿距离就行。

    测试数据

    1. Random random = new Random();
    2. int n = 3000;
    3. Point[] points = new Point[n];
    4. for (int i = 0; i < n; i++)
    5. {
    6. points[i] = new Point(random.Next(10), random.Next(10));
    7. }

    方法一:采用普通遍历法

    1. Stopwatch sw = Stopwatch.StartNew();
    2. int m = (n * n - n) / 2;
    3. List<int> list2 = new List<int>(m);
    4. for (int i = 0; i < n; i++)
    5. {
    6. Point p= points[i];
    7. for (int j = i + 1; j < n; j++)
    8. {
    9. Point p2 = points[j];
    10. int dif = Math.Abs(p.X - p2.X) + Math.Abs(p.Y - p2.Y);
    11. list2.Add(dif);
    12. }
    13. }
    14. sw.Stop();
    15. Console.WriteLine($"普通耗时:{sw.ElapsedMilliseconds}ms");

    方法二:采用SIMD加速

    1. public static int[] CalculateDistance(Point[] points)
    2. {
    3. int n = points.Length;
    4. int m = (n * n - n) >> 1;
    5. int[] ints = new int[m];
    6. int k = 0;
    7. int vsize = Vector128<int>.Count;
    8. if (n <= vsize)// 如果数据量小于等于vsize采用指针处理
    9. {
    10. fixed (Point* ptr = points)
    11. {
    12. for (int i = 0; i < n; i++)
    13. {
    14. Point* p1 = ptr + i;
    15. for (int j = i + 1; j < n; j++)
    16. {
    17. Point* p2 = ptr + j;
    18. int dif = Math.Abs(p1->X - p2->X) + Math.Abs(p1->Y - p2->Y);
    19. ints[k++] = dif;
    20. }
    21. }
    22. return ints;
    23. }
    24. }
    25. int t = 0;
    26. int[] xs = new int[n];
    27. int[] ys = new int[n];
    28. fixed (Point* ptr = points)
    29. {
    30. fixed (int* xptr = xs, yptr = ys, rptr = ints)
    31. {
    32. // 分离x与y
    33. for (int i = 0; i < n; i++)
    34. {
    35. Point* p = ptr + i;
    36. *(xptr + i) = p->X;
    37. *(yptr + i) += p->Y;
    38. }
    39. // 开始向量计算
    40. for (int i = 0; i < n; i += vsize)
    41. {
    42. Vector128<int> vx1 = *(Vector128<int>*)(xptr + i);
    43. Vector128<int> vy1 = *(Vector128<int>*)(yptr + i);
    44. for (int j = i + 1; j < n; j++)
    45. {
    46. Vector128<int> vx2 = *(Vector128<int>*)(xptr + j);
    47. Vector128<int> vy2 = *(Vector128<int>*)(yptr + j);
    48. // 向量运算
    49. var vDifference = Sse2.Add(Vector128.Abs(Sse2.Subtract(vx1, vx2)), Vector128.Abs(Sse2.Subtract(vy1, vy2)));
    50. int* maskPtr = (int*)&vDifference;
    51. int h = n - j;
    52. for (int a = 0; a < vsize; a++)
    53. {
    54. if (a >= h) break;
    55. *(rptr + t++) = *(maskPtr + a);
    56. }
    57. }
    58. }
    59. }
    60. }
    61. return ints;
    62. }

    注:根据CPU选择合适的Vector,比如Vector256、Vector512等等。本文只用Vector128.

    测试结果(Release环境):

    数据量3000500070001000030000
    普通耗时(ms)431272115383872
    向量耗时(ms)1956681901092

    结论:明显向量运算性能优于普通计算。

  • 相关阅读:
    合作式智能运输系统 应用层交互技术要求 第 1 部分:意图共享与协作
    基于51单片机十字路口交通灯仿真紧急+黄灯5s
    网站首页颜色变灰色
    React-Redux
    TiDB Lightning 前置检查
    Jupyter安装启动、登录密码问题解决
    Win:使用 Shadow Mode 查看远程用户的桌面会话
    Ubuntu20详细安装步骤
    Google Cloud Natural Language情感分析教程
    Windows安装Docker Desktop并配置镜像、修改内存占用大小
  • 原文地址:https://blog.csdn.net/ftfmatlab/article/details/140988902