C使用SSE指令来比较大量的int向量

前端之家收集整理的这篇文章主要介绍了C使用SSE指令来比较大量的int向量前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一个巨大的向量< vector< int>> (18M×128).通常我想要2行这个向量,并通过这个功能进行比较:
  1. int getDiff(int indx1,int indx2) {
  2. int result = 0;
  3. int pplus,pminus,tmp;
  4.  
  5. for (int k = 0; k < 128; k += 2) {
  6. pplus = nodeL[indx2][k] - nodeL[indx1][k];
  7. pminus = nodeL[indx1][k + 1] - nodeL[indx2][k + 1];
  8.  
  9. tmp = max(pplus,pminus);
  10. if (tmp > result) {
  11. result = tmp;
  12. }
  13. }
  14. return result;
  15. }

如你所见,函数循环通过两个行向量进行一些减法,最后返回一个最大值.这个功能将被使用一百万次,所以我想知道是否可以通过SSE指令加速.我使用Ubuntu 12.04和gcc.

当然这是微型优化,但是如果你能提供一些帮助,那么这是有帮助的,因为我对SSE一无所知.提前致谢

基准测试:

  1. int nofTestCases = 10000000;
  2.  
  3. vector<int> nodeIds(nofTestCases);
  4. vector<int> goalNodeIds(nofTestCases);
  5. vector<int> results(nofTestCases);
  6.  
  7. for (int l = 0; l < nofTestCases; l++) {
  8. nodeIds[l] = randomNodeID(18000000);
  9. goalNodeIds[l] = randomNodeID(18000000);
  10. }
  11.  
  12.  
  13.  
  14. double time,result;
  15.  
  16. time = timestamp();
  17. for (int l = 0; l < nofTestCases; l++) {
  18. results[l] = getDiff2(nodeIds[l],goalNodeIds[l]);
  19. }
  20. result = timestamp() - time;
  21. cout << result / nofTestCases << "s" << endl;
  22.  
  23. time = timestamp();
  24. for (int l = 0; l < nofTestCases; l++) {
  25. results[l] = getDiff(nodeIds[l],goalNodeIds[l]);
  26. }
  27. result = timestamp() - time;
  28. cout << result / nofTestCases << "s" << endl;

哪里

  1. int randomNodeID(int n) {
  2. return (int) (rand() / (double) (RAND_MAX + 1.0) * n);
  3. }
  4.  
  5. /** Returns a timestamp ('now') in seconds (incl. a fractional part). */
  6. inline double timestamp() {
  7. struct timeval tp;
  8. gettimeofday(&tp,NULL);
  9. return double(tp.tv_sec) + tp.tv_usec / 1000000.;
  10. }

解决方法

FWIW我将一个纯粹的SSE版本(SSE4.1)放在一起,似乎比Core i7上的原始标量码快了20%
  1. #include <smmintrin.h>
  2.  
  3. int getDiff_SSE(int indx1,int indx2)
  4. {
  5. int result[4] __attribute__ ((aligned(16))) = { 0 };
  6.  
  7. const int * const p1 = &nodeL[indx1][0];
  8. const int * const p2 = &nodeL[indx2][0];
  9.  
  10. const __m128i vke = _mm_set_epi32(0,-1,-1);
  11. const __m128i vko = _mm_set_epi32(-1,0);
  12.  
  13. __m128i vresult = _mm_set1_epi32(0);
  14.  
  15. for (int k = 0; k < 128; k += 4)
  16. {
  17. __m128i v1,v2,vmax;
  18.  
  19. v1 = _mm_loadu_si128((__m128i *)&p1[k]);
  20. v2 = _mm_loadu_si128((__m128i *)&p2[k]);
  21. v1 = _mm_xor_si128(v1,vke);
  22. v2 = _mm_xor_si128(v2,vko);
  23. v1 = _mm_sub_epi32(v1,vke);
  24. v2 = _mm_sub_epi32(v2,vko);
  25. vmax = _mm_add_epi32(v1,v2);
  26. vresult = _mm_max_epi32(vresult,vmax);
  27. }
  28. _mm_store_si128((__m128i *)result,vresult);
  29. return max(max(max(result[0],result[1]),result[2]),result[3]);
  30. }

猜你在找的C&C++相关文章