AVX 指令集并行技术优化积分计算圆周率 π

举报
ShaderJoy 发表于 2022/01/01 00:34:13 2022/01/01
【摘要】 通过 AVX 指令集并行技术优化积分计算圆周率 π 完整代码和解释如下 // AVX_PI.cpp : 定义控制台应用程序的入口点。// #include "stdafx.h"#include <iostream>#include <immintrin.h>#include <time.h> #i...

通过 AVX 指令集并行技术优化积分计算圆周率 π

完整代码和解释如下


  
  1. // AVX_PI.cpp : 定义控制台应用程序的入口点。
  2. //
  3. #include "stdafx.h"
  4. #include <iostream>
  5. #include <immintrin.h>
  6. #include <time.h>
  7. #include "timer.h"
  8. double compute_pi_naive(size_t dt)
  9. {
  10. double pi = 0.0;
  11. double delta = 1.0 / dt;
  12. for (size_t i = 0; i < dt; i++)
  13. {
  14. double x = (double)i / dt;
  15. pi += delta / (1.0 + x*x);
  16. }
  17. return pi*4.0;
  18. }
  19. double compute_pi_avx(size_t dt)
  20. {
  21. double pi = 0.0;
  22. double delta = 1.0 / dt;
  23. __m256d ymm0, ymm1, ymm2, ymm3, ymm4;
  24. ymm0 = _mm256_set1_pd(1.0); // 注意并不是对应一条指令,而是多条指令混合而成
  25. ymm1 = _mm256_set1_pd(delta);
  26. ymm2 = _mm256_set_pd(delta * 3, delta * 2, delta, 0.0); // 0.0, delta, 2*delta, 3*delta
  27. ymm4 = _mm256_setzero_pd();
  28. for (int i = 0; i <= dt - 4; i += 4)
  29. {
  30. ymm3 = _mm256_set1_pd(i * delta); // 归一化构造 x(积分区间为 0-1)
  31. ymm3 = _mm256_add_pd(ymm3, ymm2); // 分别累加四项(分别相差一个delta)
  32. ymm3 = _mm256_mul_pd(ymm3, ymm3); // 平方
  33. ymm3 = _mm256_add_pd(ymm0, ymm3); // + 1
  34. ymm3 = _mm256_div_pd(ymm1, ymm3); // delta 向量除
  35. ymm4 = _mm256_add_pd(ymm4, ymm3); // 累加
  36. }
  37. #ifndef _WIN32
  38. double tmp[4] __attribute__((aligned(32)));
  39. #else
  40. //#pragma pack(8)
  41. __declspec(align(32)) // arm 下的内存边界对齐使用 __align
  42. double tmp[4];
  43. //#pragma pack()
  44. #endif
  45. _mm256_store_pd(tmp, ymm4);
  46. pi = tmp[0] + tmp[1] + tmp[2] + tmp[3];
  47. return pi * 4.0;
  48. }
  49. int _tmain(int argc, _TCHAR* argv[])
  50. {
  51. size_t dt = 1e10;
  52. Timer timer;
  53. double pi_naive = compute_pi_naive(dt);
  54. printf("Pi = %lf, %lfms\n", pi_naive, timer.elapsed());
  55. timer.restart();
  56. double pi_avx = compute_pi_avx(dt);
  57. printf("Pi = %lf, %lfms\n", pi_avx, timer.elapsed());
  58. return 0;
  59. }

最后输出的结果,获得了 3 倍多的加速(耗时不到原来串行版本的 1/4 )

文章来源: panda1234lee.blog.csdn.net,作者:panda1234lee,版权归原作者所有,如需转载,请联系作者。

原文链接:panda1234lee.blog.csdn.net/article/details/85016597

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。