Numba函数比C ++慢,循环重新排序进一步减慢x10

时间:2015-06-19 14:19:52

标签: python performance numba

以下代码模拟从一组图像中的不同位置提取二进制字。

下面的代码中的Numba包装函数wordcalc有两个问题:

  1. 与C ++中的类似实现相比,它慢了3倍。
  2. 最奇怪的是,如果你切换“ibase”和“ibit”for循环的顺序,速度会下降10倍(!)。这在C ++实现中不会发生,而C ++实现仍然不受影响。
  3. 我正在使用WinPython 2.7中的Numba 0.18.2

    导致这种情况的原因是什么?

    imDim = 80
    numInsts = 10**4
    numInstsSub = 10**4/4
    bitsNum = 13;
    
    Xs = np.random.rand(numInsts, imDim**2)       
    iInstInds = np.array(range(numInsts)[::4])
    baseInds = np.arange(imDim**2 - imDim*20 + 1)
    ofst1 = np.random.randint(0, imDim*20, bitsNum)
    ofst2 = np.random.randint(0, imDim*20, bitsNum)
    
    @nb.jit(nopython=True)
    def wordcalc(Xs, iInstInds, baseInds, ofst, bitsNum, newXz):
        count = 0
        for i in iInstInds:
            Xi = Xs[i]        
            for ibit in range(bitsNum):
                for ibase in range(baseInds.shape[0]):                    
                    u = Xi[baseInds[ibase] + ofst[0, ibit]] > Xi[baseInds[ibase] + ofst[1, ibit]]
                    newXz[count, ibase] = newXz[count, ibase] | np.uint16(u * (2**ibit))
            count += 1
        return newXz
    
    ret = wordcalc(Xs, iInstInds, baseInds, np.array([ofst1, ofst2]), bitsNum, np.zeros((iInstInds.size, baseInds.size), dtype=np.uint16))
    

1 个答案:

答案 0 :(得分:3)

通过从np.uint16(u * (2**ibit))更改为np.uint16(u << ibit),我获得了4倍的加速;即用比特移位替换2的幂,这应该是等价的(对于整数)。

您的C ++编译器本身可能很有可能进行此替换。

交换两个循环的顺序对我的原始版本(5%)和我的优化版本(15%)都有一点不同,所以我不能认为我可以对此做出有用的评论

如果你真的想比较Numba和C ++,你可以在导入Numba之前通过os.environ['NUMBA_DUMP_ASSEMBLY']='1'查看已编译的Numba函数。 (虽然这显然非常复杂)。

作为参考,我使用的是Numba 0.19.1。