【问题标题】:the code doesn't speed up while using Intel Intrinsics使用 Intel Intrinsics 时代码没有加速
【发布时间】:2016-06-08 10:16:13
【问题描述】:

我正在使用内部函数来加速正在运行的 openCV 代码。但是在我用 Intrinsics 替换代码之后,代码的运行时成本几乎相同,甚至可能更糟。我无法弄清楚这是什么以及为什么会发生这种情况。我一直在寻找这个问题很长一段时间,但注意到变化。如果有人可以帮助我,我们将不胜感激。非常感谢你!这是我的代码

      // if useSSE is true,run the code with intrinsics and takes 1.45ms in my computer 
      // and if not run the general code and takes the same time.
     cv::Mat<float> results(shape.rows,2);
     if (useSSE) {
        float* pshape = (float*)shape.data;
        results = shape.clone();
        float* presults = (float*)results.data;
        // use SSE
        __m128 xyxy_center = _mm_set_ps(bbox.center_y, bbox.center_x, bbox.center_y, bbox.center_x);

        float bbox_width = bbox.width/2;
        float bbox_height = bbox.height/2;
        __m128 xyxy_size = _mm_set_ps(bbox_height, bbox_width, bbox_height, bbox_width);
        gettimeofday(&start, NULL); // this is for counting time

        int shape_size = shape.rows*shape.cols;
        for (int i=0; i<shape_size; i +=4) {
            __m128 a = _mm_loadu_ps(pshape+i);
            __m128 result = _mm_div_ps(_mm_sub_ps(a, xyxy_center),  xyxy_size);
            _mm_storeu_ps(presults+i, result);
        }
    }else {
        //SSE TO BE DONE
        for (int i = 0; i < shape.rows; i++){
            results(i, 0) = (shape(i, 0) - bbox.center_x) / (bbox.width / 2.0);
            results(i, 1) = (shape(i, 1) - bbox.center_y) / (bbox.height / 2.0);
        }
    }
    gettimeofday(&end, NULL);
    diff = 1000000*(end.tv_sec-start.tv_sec)+end.tv_sec-start.tv_usec;
    std::cout<<diff<<"-----"<<std::endl;
    return results;

【问题讨论】:

  • 一个工作代码可以帮助你得到一些答案。请看如何做一个minimal reproducible example
  • 另外,你应该描述你的代码做什么。
  • 你真的需要div_ps 还是可以乘以倒数?
  • 哪个编译器?例如,如果您使用的是 Windows 和 VS2012 或更高版本,您可能会发现这些简单的for 循环是automatically vectorized
  • 调用 gettimeofday 可能会使其他一切相形见绌。您应该考虑将时间从函数体中提升出来,并改为对它进行 1000000 次调用。此外,您似乎没有调整自己的价值观。

标签: c++ opencv sse intrinsics


【解决方案1】:
  1. 如果 shape.rows % 2 == 1,您的 SSE 优化将损坏结果变量附近的内存
  2. 尽量避免在循环中使用 i 变量,直接使用指针。编译器可能会优化额外的加运算,也可能不会。
  3. 用乘法代替除法:

    float bbox_width_inv = 2./bbox.width;
    float bbox_height_inv = 2./bbox.height;
    __m128 xyxy_size = _mm_set_ps(bbox_height, bbox_width, bbox_height, bbox_width);
    float* p_shape_end = p_shape + shape.rows*shape.cols;
    float* p_shape_end_batch = p_shape + shape.rows*shape.cols & (~3);
    for (; p_shape<p_shape_end_batch; p_shape+=4, presults+=4) {
        __m128 a = _mm_loadu_ps(pshape);
        __m128 result = _mm_mul_ps(_mm_sub_ps(a, xyxy_center),  xyxy_size_inv);
        _mm_storeu_ps(presults, result);
    }
    while (p_shape < p_shape_end) {
        presults++ = (p_shape++ - bbox.center_x) * bbox_width_inv;
        presults++ = (p_shape++ - bbox.center_y) * bbox_height_inv;
    }
    
  4. 尝试反汇编从内在函数生成的代码,并确保有足够的寄存器来执行您的操作,并且不会将临时结果存储到 RAM 中

【讨论】:

  • 感谢您给我的所有建议!首先,shape.rows 默认为 2,抱歉我没有说清楚。对于其他的,我已经尝试了这些改进,但它对运行时间的结果没有任何影响。
  • 将除法改为乘法没有帮助?
  • 不...是的,这很奇怪
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-23
  • 2019-07-06
  • 2013-02-28
  • 2017-03-05
  • 1970-01-01
相关资源
最近更新 更多