下面的代码在对象检测程序中被大量调用,并且花费大约80%的执行时间。有什么办法可以大大加快速度吗?

#define CALC_SUM_(p0, p1, p2, p3, offset) ((p0)[offset] - (p1)[offset] - (p2)[offset] + (p3)[offset])
inline int calc_lbp2(float *p[], int offset)
{
    int cval = CALC_SUM_( p[5], p[6], p[9], p[10], offset );

    return (CALC_SUM_( p[0],  p[1],  p[4],  p[5],  offset ) >= cval ? 128 : 0) |   // 0
           (CALC_SUM_( p[1],  p[2],  p[5],  p[6],  offset ) >= cval ? 64 : 0) |    // 1
           (CALC_SUM_( p[2],  p[3],  p[6],  p[7],  offset ) >= cval ? 32 : 0) |    // 2
           (CALC_SUM_( p[6],  p[7],  p[10], p[11], offset ) >= cval ? 16 : 0) |  // 5
           (CALC_SUM_( p[10], p[11], p[14], p[15], offset ) >= cval ? 8 : 0)|  // 8
           (CALC_SUM_( p[9],  p[10], p[13], p[14], offset ) >= cval ? 4 : 0)|   // 7
           (CALC_SUM_( p[8],  p[9],  p[12], p[13], offset ) >= cval ? 2 : 0)|    // 6
           (CALC_SUM_( p[4],  p[5],  p[8],  p[9],  offset ) >= cval ? 1 : 0);
}


我尝试了SSE,但该程序花费了大约50毫秒(原始执行时间约为170毫秒):

inline int calc_lbp_sse(float *p[], int offset)
{
    static unsigned short bits[] = {0x0080, 0x0040, 0x0020, 0x0010, 0x0008, 0x0004, 0x0002, 0x0001};
    short c = CALC_SUM_( p[5], p[6], p[9], p[10], offset );
    __m128i a = _mm_setr_epi16
                (
                    CALC_SUM_( p[0],  p[1],  p[4],  p[5],  offset ),
                    CALC_SUM_( p[1],  p[2],  p[5],  p[6],  offset ),
                    CALC_SUM_( p[2],  p[3],  p[6],  p[7],  offset ),
                    CALC_SUM_( p[6],  p[7],  p[10], p[11], offset ),
                    CALC_SUM_( p[10], p[11], p[14], p[15], offset ),
                    CALC_SUM_( p[9],  p[10], p[13], p[14], offset ),
                    CALC_SUM_( p[8],  p[9],  p[12], p[13], offset ),
                    CALC_SUM_( p[4],  p[5],  p[8],  p[9],  offset )
                );
    __m128i b = _mm_setr_epi16(c, c, c, c, c, c, c, c);

    __m128i res = _mm_cmplt_epi16(b,a);
    unsigned short* vals = (unsigned short*)&res;

    return ((vals[0]&bits[0]) | (vals[1]&bits[1]) | (vals[2]&bits[2]) | (vals[3]&bits[3]) |
            (vals[4]&bits[4]) | (vals[5]&bits[5]) |(vals[6]&bits[6]) |(vals[7]&bits[7]));
}

最佳答案

我在台式机上运行了200000000次功能,耗时5.3秒。然后我更改了这一行:

int cval = CALC_SUM_( p[5], p[6], p[9], p[10], offset );


对此:

float cval = CALC_SUM_( p[5], p[6], p[9], p[10], offset );


我重新进行了相同的测试,现在花了3.0秒。现在,我对LBP并不熟悉,但似乎您并不是故意将中心值转换为int。根据我对LBP的了解,您只是将相邻值与中心值进行比较。但是,如果强制转换为int实际上很重要,则只需忽略此答案即可。

顺便说一句,我尝试了japreiss提出的用? :替换<< 6的建议,但是无论哪种方式,我都获得了完全相同的速度。因此,显然编译器已经对此进行了优化(我正在使用gcc -O3)。

关于c - 如何加快以下代码以显着计算CPU上的LBP?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/27370543/

10-11 07:08