使用数学函数优化此java代码的建议
我有以下java代码。我正在尝试优化功能使用数学函数优化此java代码的建议,java,Java,我有以下java代码。我正在尝试优化功能 while(pStart < audio.length) { int pEnd = Math.round(pStart + winSize*Fs); int windowEnd = Math.min(pEnd, audio.length); double[] window = new double[fftSize*2]; for(int i = pStart; i
while(pStart < audio.length) {
int pEnd = Math.round(pStart + winSize*Fs);
int windowEnd = Math.min(pEnd, audio.length);
double[] window = new double[fftSize*2];
for(int i = pStart; i < windowEnd; i++) {
window[(i-pStart)*2] = audio[i];
}
fft.complexForward(window);
double fftVal;
for(int i = 0; i < fftSize/2; i++) {
fftVal = Math.sqrt((window[i*2] * window[i*2]) + (window[i*2+1] * window[i*2+1] ));
powerAll[i][index] = 20 * Math.log10(
Math.abs(fftVal) / (windowEnd - pStart));
}
index++;
pStart = pStart + windowSlide;
}
while(pStart
根据跟踪文件进行计时:
总计2500毫秒
fft~500ms
自我监测约900毫秒
第二个循环约900毫秒
现在,我的重点是优化第二个for循环。我不能改变fft函数
在同一个问题上,我不确定为什么跟踪程序报告“self”为900毫秒。您可以做的简单优化是将
window[I*2]
和window[I*2+1]
的值存储在变量中,并在sqrt()
方法中使用它们,这将减少数组访问的次数
除此之外,如果你能说出你想做什么,我们可能会更好地帮助你。你可以做的简单优化是将
window[i*2]
和window[i*2+1]
的值存储在一个变量中,并在sqrt()
方法中使用它们,这将减少数组访问的次数
除此之外,如果你能说出你想做什么,我们可能会更好地帮助你。你的代码很容易成为并行化的目标。你可以:
ForkJoin
,它可以为您处理许多方面的问题李>
parallelStream
处理任务编写李>
我的选择当然是第三,如果没有别的,那就是为了好玩
我花了一些时间在我的设置中使用jmh测量您的代码。
窗口
数组的每个条目需要14纳秒。考虑到所做的计算量,我认为这已经是一个很好的结果,并且不能有任何显著的改进。您的代码很容易成为并行化的目标。你可以:
ForkJoin
,它可以为您处理许多方面的问题李>
parallelStream
处理任务编写李>
我的选择当然是第三,如果没有别的,那就是为了好玩
我花了一些时间在我的设置中使用jmh测量您的代码。
窗口
数组的每个条目需要14纳秒。考虑到所做的计算量,我认为这已经是一个很好的结果,并且不能有任何显著的改进。原始代码可以通过应用log函数的数学属性来简化
考虑从原始代码中提取的以下函数:
double original( double[] window, int i, int windowEnd, int pStart ) {
double fftVal = Math.sqrt(
( window[ i * 2 ] * window[ i * 2 ] )
+ ( window[ i * 2 + 1 ] * window[ i * 2 + 1 ] )
);
return 20 * Math.log10(
Math.abs( fftVal ) / ( windowEnd - pStart ) );
}
基本上,我们在伪代码中有以下函数:
x = sqrt(w[2i]^2 + w[2i+1]^2)
return 20 * log( abs(x) / ( windowEnd - pStart ) )
- abs不是必需的,因为sqrt()的值是非负的
- 对数(X/Y)==对数(X)-对数(Y)
- 对数(sqrt(X))=0.5对数(X)
- 日志(windowEnd-pStart)可以预先计算并兑现
double variant( double[] window, int i, int windowEnd, int pStart ) {
// w[2i]^2 + w[2i+1]^2
double temp1 = window[ i * 2 ] * window[ i * 2 ]
+ window[ i * 2 + 1 ] * window[ i * 2 + 1 ];
// apply log(sqrt(X)) == log(X^0.5) == 0.5 log(X)
double temp2 = 0.5 * Math.log10( temp1 );
// calculate the value of Math.log10( windowEnd - pStart )
// (and cache it outside of the function)
double tempConst3 = Math.log10( windowEnd - pStart );
// apply log(X/Y) == log(X) - log(Y)
double temp4 = temp2 - tempConst3;
return 20 * temp4;
}
原始代码可以通过应用log函数的数学特性来简化 考虑从原始代码中提取的以下函数:
double original( double[] window, int i, int windowEnd, int pStart ) {
double fftVal = Math.sqrt(
( window[ i * 2 ] * window[ i * 2 ] )
+ ( window[ i * 2 + 1 ] * window[ i * 2 + 1 ] )
);
return 20 * Math.log10(
Math.abs( fftVal ) / ( windowEnd - pStart ) );
}
基本上,我们在伪代码中有以下函数:
x = sqrt(w[2i]^2 + w[2i+1]^2)
return 20 * log( abs(x) / ( windowEnd - pStart ) )
- abs不是必需的,因为sqrt()的值是非负的
- 对数(X/Y)==对数(X)-对数(Y)
- 对数(sqrt(X))=0.5对数(X)
- 日志(windowEnd-pStart)可以预先计算并兑现
double variant( double[] window, int i, int windowEnd, int pStart ) {
// w[2i]^2 + w[2i+1]^2
double temp1 = window[ i * 2 ] * window[ i * 2 ]
+ window[ i * 2 + 1 ] * window[ i * 2 + 1 ];
// apply log(sqrt(X)) == log(X^0.5) == 0.5 log(X)
double temp2 = 0.5 * Math.log10( temp1 );
// calculate the value of Math.log10( windowEnd - pStart )
// (and cache it outside of the function)
double tempConst3 = Math.log10( windowEnd - pStart );
// apply log(X/Y) == log(X) - log(Y)
double temp4 = temp2 - tempConst3;
return 20 * temp4;
}
如果你陈述了你想做什么,那么提出解决方案就很容易了!大量的时间意味着什么?。除非fftVal真的是个大数字,否则就不应该是这样,除非笨重的含义已经改变了!是不是
window[i*2]*window[i*2]
和to do:Math.pow(window[i*2],2)
一样?@Eldarion它在功能上是一样的,但可能快得多。您是否对FFT结果进行了预处理,而没有考虑到您正在测量的性能?因为我发现很难相信你发布的代码可以和FFT处理本身占用相同的时间顺序。如果你陈述你正在尝试做什么,那么提出解决方案就很容易了!大量的时间意味着什么?。除非fftVal真的是个大数字,否则就不应该是这样,除非笨重的含义已经改变了!是不是window[i*2]*window[i*2]
和to do:Math.pow(window[i*2],2)
一样?@Eldarion它在功能上是一样的,但可能快得多。您是否对FFT结果进行了预处理,而没有考虑到您正在测量的性能?因为我发现很难相信您发布的代码可以与FFT处理本身占用相同的时间顺序。JIT将处理减少的数组访问。JIT将处理减少的数组访问。谢谢,我看了java8。将尝试选项3。我编辑了这篇文章,包括完整的代码和计时汉克,我看了java8。将尝试选项3。我编辑了这篇文章,包括了完整的代码和计时,尽管这是一种新颖的方法,但是我最终使用了两个Math.log10调用,这是非常昂贵的。我测试了它,我的运行时间实际上增加了。我已经删除了abs函数。我已经两次提到可以缓存Math.log10(windowEn