模数优化

时间:2014-07-16 10:11:49

标签: c optimization

我有一个C程序,可以对大型数组进行大量的交换操作。它在紧密的循环中有一个模运算。事实上,[-N | N [N范围内的整数是2的幂,它应该被包装为[0,N [。

N = 4的实例:-4 => 0,-3 => 1,-2 => 2,-1 => 3,0 => 0,...,3 => 3

起初我尝试了下面的版本1但是很惊讶版本2实际上显然更快,即使它有一个条件表达式。

对于这种特殊情况,您能解释为什么版本2比版本1快吗?

版本1:

#define N (1<<(3*5))

inline int modBitAnd(int x)
{
    return (x & (N-1));
}

运行时间:17.1秒(整个程序)

版本2:

inline int modNeg1(int x)
{
    return (x < 0 ? x + N : x);
}

运行时间:14.6秒(整个程序)

计划在GCC 4.8.2上编制。使用-std = c99 -O3。

修改

这是我程序中的主循环:

int en(uint16_t* p, uint16_t i, uint16_t v)
{
    uint16_t n1 = p[modNeg1((int)i - 1)];
    uint16_t n2 = p[modBitAnd((int)i + 1)];
    uint16_t n3 = p[modNeg1((int)i - C_WIDTH)];
    uint16_t n4 = p[modBitAnd((int)i + C_WIDTH)];
    return d(n1,v) + d(n2,v) + d(n3,v) + d(n4,v);
}

void arrange(uint16_t* p)
{
    for(size_t i=0; i<10000000; i++) {
        uint16_t ia = random(); // random integer [0|2^15[
        uint16_t va = p[ia];
        uint16_t ib = random(); // random integer [0|2^15[
        uint16_t vb = p[ib];
        if(en(p,ia,vb) + en(p,ib,va) < en(p,ia,va) + en(p,ib,vb)) {
            p[ia] = vb;
            p[ib] = va;
        }
    }
}

int d(uint16_t a, uint16_t b)是距离函数,例如abs((int)a-(int)b)

这是p的初始化方式:

uint16_t* p = malloc(sizeof(uint16_t)*N);
for(unsigned i=0; i<N; i++) *p++ = i;

首先我在任何地方使用了modBitAnd,但发现modNeg1对于可以使用它的两种情况来说实际上更快。

1 个答案:

答案 0 :(得分:0)

首先take a few stackshots找出实际上的时间。您的mod函数会抓取一部分样本,但您还有两次调用random,加上相当数量的数组索引。此外,看起来您已经有四次调用en且一些参数相同,因此您的模块化可能导致重复调用mod函数。