【MPI程序】向量乘法,向量点积(高性能计算)

末蓝、 2022-04-18 00:28 419阅读 0赞

简述

假设,调用的节点数量整除向量的秩。

高性能算法

让0节点来读取文件数据
所有的节点都负责计算,然后,这里使用的是块分配法。
其他的都是接受到数据之后,再进行计算。
而0节点由于需要负责传输和调度,所以它会在发送数据之后,再进行计算本地的块。之后,再来接受和保存数据。

运行效果

在这里插入图片描述

输入的数据为:

  1. 10
  2. 1 2 3 4 5 6 7 8 9 10
  3. 2 3 4 5 6 7 8 9 10 11
  4. 8

代码

  1. #include<stdio.h>
  2. #include<string.h>
  3. #include<mpi.h>
  4. #pragma warning(disable : 4996)
  5. #define MAX_STRING 100
  6. using namespace std;
  7. #include <fstream>
  8. #include <iostream>
  9. int Find_bin(double x, double *bin_maxes, int bin_count) {
  10. for (int i = 0; i < bin_count; ++i) {
  11. if (x < bin_maxes[i]) return i;
  12. }
  13. return bin_count; // 越界
  14. }
  15. int main(void) {
  16. double *local_vec1, *local_vec2;
  17. int len;
  18. double scalar, local_sum = 0;
  19. int comm_sz;
  20. int my_rank;
  21. int divided_len;
  22. MPI_Init(NULL, NULL);
  23. MPI_Comm_size(MPI_COMM_WORLD, &comm_sz);
  24. MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
  25. // 假设 n % comm_sz = 0 整除
  26. // 只有一个线程的时候不操作
  27. if (comm_sz <= 1) {
  28. MPI_Finalize();
  29. return 0;
  30. }
  31. if (my_rank == 0) {
  32. ifstream cin("D:\\C++\\VS\\repo\\MPI-DEMO\\MPI-DEMO\\input.txt");
  33. cin >> len; // 输入数据长度
  34. local_vec1 = new double[len];
  35. local_vec2 = new double[len];
  36. for (int i = 0; i < len; ++i) cin >> local_vec1[i];
  37. for (int i = 0; i < len; ++i) cin >> local_vec2[i];
  38. cin >> scalar;
  39. divided_len = len / comm_sz;
  40. double * sub_vec = new double[divided_len];
  41. // 发送子串长度
  42. for (int i = 1; i < comm_sz; ++i) {
  43. MPI_Send(&divided_len, 1, MPI_INT, i, 3, MPI_COMM_WORLD);
  44. }
  45. // 发送第一个串
  46. int target = 1;
  47. for (int i = divided_len; i < len; i += divided_len) {
  48. for (int j = 0; j < divided_len; ++j) {
  49. sub_vec[j] = local_vec1[j + i];
  50. }
  51. MPI_Send(sub_vec, divided_len, MPI_DOUBLE, target, 0, MPI_COMM_WORLD);
  52. target++;
  53. }
  54. // 发送第二个串
  55. target = 1;
  56. for (int i = divided_len; i < len; i += divided_len) {
  57. for (int j = 0; j < divided_len; ++j) {
  58. sub_vec[j] = local_vec2[j + i];
  59. }
  60. MPI_Send(sub_vec, divided_len, MPI_DOUBLE, target, 1, MPI_COMM_WORLD);
  61. target++;
  62. }
  63. // 发送因子
  64. for (int i = 1; i < target; ++i) {
  65. MPI_Send(&scalar, 1, MPI_DOUBLE, i, 2, MPI_COMM_WORLD);
  66. }
  67. // 计算本地的数据
  68. for (int i = 0; i < divided_len; ++i) {
  69. local_sum += (local_vec1[i] * local_vec2[i]);
  70. local_vec1[i] *= scalar;
  71. local_vec2[i] *= scalar;
  72. }
  73. // 接受第一个串
  74. target = 1;
  75. for (int i = divided_len; i < len; i += divided_len) {
  76. MPI_Recv(sub_vec, divided_len, MPI_DOUBLE, target, 0, MPI_COMM_WORLD, MPI_STATUSES_IGNORE);
  77. for (int j = 0; j < divided_len; ++j) {
  78. local_vec1[j + i] = sub_vec[j];
  79. }
  80. target++;
  81. }
  82. // 接受第二个串
  83. target = 1;
  84. for (int i = divided_len; i < len; i += divided_len) {
  85. MPI_Recv(sub_vec, divided_len, MPI_DOUBLE, target, 1, MPI_COMM_WORLD, MPI_STATUSES_IGNORE);
  86. for (int j = 0; j < divided_len; ++j) {
  87. local_vec2[j + i] = sub_vec[j];
  88. }
  89. target++;
  90. }
  91. // 接受部分和
  92. for (int i = 1; i < target; ++i) {
  93. MPI_Recv(&scalar, 1, MPI_DOUBLE, i, 2, MPI_COMM_WORLD, MPI_STATUSES_IGNORE);
  94. local_sum += scalar;
  95. }
  96. // 输出
  97. for (int i = 0; i < len; ++i) {
  98. cout << local_vec1[i] << " ";
  99. }cout << endl;
  100. for (int i = 0; i < len; ++i) {
  101. cout << local_vec2[i] << " ";
  102. }cout << endl;
  103. cout << local_sum << endl;
  104. delete[] sub_vec;
  105. delete[] local_vec1;
  106. delete[] local_vec2;
  107. } // 运算的子节点
  108. else {
  109. MPI_Recv(&divided_len, 1, MPI_INT, 0, 3, MPI_COMM_WORLD, MPI_STATUSES_IGNORE);
  110. local_vec1 = new double[divided_len];
  111. local_vec2 = new double[divided_len];
  112. MPI_Recv(local_vec1, divided_len, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, MPI_STATUSES_IGNORE);
  113. MPI_Recv(local_vec2, divided_len, MPI_DOUBLE, 0, 1, MPI_COMM_WORLD, MPI_STATUSES_IGNORE);
  114. MPI_Recv(&scalar, 1, MPI_DOUBLE, 0, 2, MPI_COMM_WORLD, MPI_STATUSES_IGNORE);
  115. for (int i = 0; i < divided_len; ++i)
  116. {
  117. local_sum += local_vec1[i] * local_vec2[i];
  118. local_vec1[i] *= scalar;
  119. local_vec2[i] *= scalar;
  120. }
  121. MPI_Send(local_vec1, divided_len, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD);
  122. MPI_Send(local_vec2, divided_len, MPI_DOUBLE, 0, 1, MPI_COMM_WORLD);
  123. MPI_Send(&local_sum, 1, MPI_DOUBLE, 0, 2, MPI_COMM_WORLD);
  124. delete[] local_vec1;
  125. delete[] local_vec2;
  126. }
  127. MPI_Finalize();
  128. return 0;
  129. }

发表评论

表情:
评论列表 (有 0 条评论,419人围观)

还没有评论,来说两句吧...

相关阅读

    相关 torch 乘-向量乘法

    在`PyTorch`中,可以使用`torch.dot()`函数来计算两个一维张量的点乘(内积)。点乘操作会将两个一维张量按元素相乘,并返回一个标量(0维张量)作为结果。 下面