SSE指令集加速运算

原文:https://blog.csdn.net/nick_wong/article/details/7779381

先上代码:

 
  1. /*g++ -msse2 main.cpp -lrt*/

  2.  
  3. #include <iostream>

  4. #include <xmmintrin.h>//SSE指令集需包含词头文件

  5. #include <time.h>

  6. using namespace std;

  7.  
  8. #define N 120

  9. int main() {

  10.  
  11. struct timespec tpstart,tpend;

  12. clock_gettime(CLOCK_MONOTONIC, &tpstart);

  13. /////////////////do something

  14. {

  15.  
  16. __m128 *p1,*p2,*p3;//__m128是一个长128位的数据类型,存放在寄存器中

  17. __attribute(aligned(128)) float f1[N],f2[N],f3[N];//新建一些浮点型数组

  18. /*__attribute(aligned(128))强制使编译器在给f1等分配内存空间时对齐在128位(8字节)上*/

  19. //cout<<f1<<"\t"<<(int)f1%128<<endl;

  20. /*运行此条语句可以看出地址f1总是128的倍数,在内存上即是总存在一行上,使得总线取值时能够一次取完*/

  21. for(int i=0; i<N; i++) {

  22. f1[i]=i+0.12;

  23. f2[i]=i+0.16;

  24. }

  25. for(int time=0; time<10000; time++) {

  26. p1=(__m128*)f1;

  27. p2=(__m128*)f2;

  28. p3=(__m128*)f3;

  29. for(int i=0; i<N; i+=4) {

  30. *p3=_mm_mul_ps(*p1,*p2);//此函数封装了一些汇编原语,使得可以同时计算4个值的乘法

  31. p3++;

  32. p2++;

  33. p1++;

  34. }

  35. /*注意N的取值,N取为4的整数倍,使得最后一次调用SSE指令时刚好能全部处理完。否则容易引发段错误。

  36. 所以,即使不能使用完,也一定要申请4的整数背空间*/

  37. }

  38. }

  39. /////////////////done

  40. clock_gettime(CLOCK_MONOTONIC, &tpend);

  41. long timedif = (tpend.tv_sec-tpstart.tv_sec)*1000*1000+(tpend.tv_nsec-tpstart.tv_nsec)/1000;

  42. cout<<"SSE:\t"<<timedif<<endl;

  43.  
  44. /////////////////////////不采用SSE指令/////////////////////////////////////

  45.  
  46.  
  47. clock_gettime(CLOCK_MONOTONIC, &tpstart);

  48. /////////////////do something

  49. {

  50.  
  51. float f1[N],f2[N],f3[N];

  52. for(int i=0; i<N; i++) {

  53. f1[i]=i+0.12;

  54. f2[i]=i+0.16;

  55. }

  56.  
  57. for(int time=0; time<10000; time++) {

  58. for(int i=0; i<N; i++) {

  59. f3[i]=f1[i]*f2[i];

  60. }

  61. }

  62. }

  63. /////////////////done

  64. clock_gettime(CLOCK_MONOTONIC, &tpend);

  65. timedif = (tpend.tv_sec-tpstart.tv_sec)*1000*1000+(tpend.tv_nsec-tpstart.tv_nsec)/1000;

  66. cout<<"noSSE:\t"<<timedif<<endl;

  67.  
  68. return 0;

  69. }


注意计时函数需要包含的头文件和编译选项,clock_gettime函数能精确到纳秒。

运行结果为:

SSE:    4929
noSSE:    9980

以微秒为单位,平均提高约两倍。

下面是另一份代码,演示如何动态申请空间,注意内存对齐:

 
  1. #include <xmmintrin.h>

  2. #include <iostream>

  3. using namespace std;

  4. const int N=120;

  5.  
  6. int main()

  7. {

  8. __m128 *p1,*p2,*p3;

  9. __attribute(aligned(128)) float *pf1,*pf2,*pf3;

  10. pf1=(float *)_mm_malloc(sizeof(float)*N,128);

  11. pf2=(float *)_mm_malloc(sizeof(float)*N,128);

  12. pf3=(float *)_mm_malloc(sizeof(float)*N,128);

  13. cout<<(int)pf1%128<<endl;

  14. cout<<(int)pf2%128<<endl;

  15. cout<<(int)pf3%128<<endl;

  16.  
  17. for(int i=0;i<N;i++){

  18. pf1[i]=i+0.12;

  19. pf2[i]=i+0.16;

  20. };

  21. p1=(__m128*)pf1;

  22. p2=(__m128*)pf2;

  23. p3=(__m128*)pf3;

  24. for(int i=0;i<N;i+=4){

  25. *p3=_mm_add_ps(*p1,*p2);

  26. p3++;

  27. p2++;

  28. p1++;

  29. }

  30. _mm_free(pf1);

  31. _mm_free(pf2);

  32. _mm_free(pf3);

  33. return 0;

  34. }

猜你喜欢

转载自blog.csdn.net/xz4385478/article/details/81198567
今日推荐