Java中的快速整数除法

时间:2017-03-16 17:18:34

标签: java performance division integer-division

众所周知,整数除法运算缓慢(通常比整数乘法慢几倍)。但是,如果需要使用固定除数执行许多除法运算,则可以对除数进行一些预处理并替换" /"乘法和位操作(Hacker's Delight中的第10章)。

在我测试过的情况下,如果除数是编译时常数(例如master.vm.provision :salt do |salt| salt.install_master = true salt.master_pub = 'id_rsa.pub' salt.master_key = 'id_rsa' salt.install_type = 'stable' salt.master_config = 'master' salt.minion_config = 'salt-local' end ),JVM将执行该操作,并使用乘法和位操作将所有除法替换为static final long DIVISOR = 12345L;。我在同一种技巧中感兴趣,但只有在运行时才知道除数。

例如,以下(慢)方法:

DIVISOR

可以替换为:

void reduceArraySlow(long[] data, long denominator){
    for(int i = 0; i < data.length; ++i)
        data[i] = data[i] / denominator;
}

必须更快地完成工作,因为所有void reduceArrayFast(long[] data, long denominator){ SomeMagicStructure magic = computeMagic(denominator); for(int i = 0; i < data.length; ++i) // computes data[i] / denominator data[i] = doFastDivision(data[i], magic); } 操作都被更快的操作所取代(并且因为除法在CPU中没有流水线化)。

1 个答案:

答案 0 :(得分:2)

有一个众所周知的用于快速整数除法的C / C ++ libdivide库,我可以使用这个库来改编Java libdivide4j

使用libdivide4j快速划分如下:

/

一个简单的基准

void reduceArrayFast(long[] data, long denominator){
    FastDivision.Magic magic = FastDivision.magicSigned(denominator);
    for(int i = 0; i < data.length; ++i)
        // computes data[i] / denominator
        data[i] = FastDivision.divideSignedFast(data[i], magic);
}

显示普通public void benchmark() throws Exception { Random rnd = new Random(); int nIterations = 10000; //let the JIT to optimize something for (int att = 0; att < nIterations; att++) { long[] data = new long[1000]; for (int i = 0; i < data.length; i++) data[i] = rnd.nextLong(); long denominator = rnd.nextLong(); long[] slow = data.clone(); long start = System.nanoTime(); reduceArraySlow(slow, denominator); long slowTime = System.nanoTime() - start; long[] fast = data.clone(); start = System.nanoTime(); reduceArrayFast(fast, denominator); long fastTime = System.nanoTime() - start; Assert.assertArrayEquals(slow, fast); // print last 100 timings (JVM already warmed up) if (att > nIterations - 100) { System.out.println("\"/\" operation: " + slowTime); System.out.println("Fast division: " + fastTime); System.out.println(""); } } } 和快速划分(Core i7,jdk8 64位)的以下时间(纳秒):

/