众所周知,整数除法运算缓慢(通常比整数乘法慢几倍)。但是,如果需要使用固定除数执行许多除法运算,则可以对除数进行一些预处理并替换" /"乘法和位操作(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中没有流水线化)。
答案 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位)的以下时间(纳秒):
/