从Java和纯C运行C代码的区别
我必须在我的android项目中使用DFFT。我找到了图书馆并决定使用它 我编写了如下JNI函数:从Java和纯C运行C代码的区别,java,c,performance,java-native-interface,Java,C,Performance,Java Native Interface,我必须在我的android项目中使用DFFT。我找到了图书馆并决定使用它 我编写了如下JNI函数: #import ... ... kiss_fft_cfg cfg; // kiss_fft config int nfft; // chunk size // allocating config for fft extern "C" void Java_xxx_yyy_zzz_MyActivity_allocFFT(JNIEnv *env,jobject /* th
#import ...
...
kiss_fft_cfg cfg; // kiss_fft config
int nfft; // chunk size
// allocating config for fft
extern "C"
void
Java_xxx_yyy_zzz_MyActivity_allocFFT(JNIEnv *env,jobject /* this */,jint chunkSize){
cfg = kiss_fft_alloc(chunkSize,false,0,0);
nfft = chunkSize;
}
// calculate fft
extern "C"
jdoubleArray
Java_xxx_yyy_zzz_MyActivity_doFFT(JNIEnv *env,jobject /* this */,jshortArray data) {
kiss_fft_cpx *cx_in, *cx_out;
cx_in = new kiss_fft_cpx[nfft];
cx_out = new kiss_fft_cpx[nfft];
jshort *body = env->GetShortArrayElements(data, 0);
int chunksCnt = ceil(env->GetArrayLength(data)/nfft);
double *amps = new double[chunksCnt*nfft/2];
for(int iter=0; iter<chunksCnt; ++iter) {
// fill cx_in
for (int oter = 0; oter < nfft; ++oter) {
cx_in[oter].r = body[iter*nfft + oter];
cx_in[oter].i = 0.0;
}
// do FFT
kiss_fft(cfg, cx_in, cx_out);
// find amplitudes and save it
for (int oter = 0; oter < nfft / 2; ++oter)
amps[iter * nfft / 2 + oter] =
sqrt(pow(cx_out[oter].r, 2) + pow(cx_out[oter].i, 2)) / nfft;
}
jdoubleArray amplitudes = env->NewDoubleArray(chunksCnt*nfft/2);
env->SetDoubleArrayRegion(amplitudes,0,chunksCnt*nfft/2,&s[0]);
delete[] cx_in;
delete[] cx_out;
delete[] amps;
env->ReleaseShortArrayElements(data, body, JNI_ABORT);
return amplitudes;
}
// freeing resources
extern "C"
void
Java_xxx_yyy_zzz_MyActivity_freeFFT(JNIEnv *env,jobject /* this */){
free(cfg);
}
正如你们所看到的,fft计算的时间有时看起来很奇怪——是平均值的10倍吗
我试着用同一个库在纯C中做同样的测试,但没有这样的结果——所有的计算时间大致相等
所以,假设问题出在我的本地代码中是合乎逻辑的,可能是我忘了做一些重要的事情,我不知道。请帮帮我。这可能有很多原因,我的最佳猜测是垃圾收集有时会启动以回收内存。这也是android吗?你可以尝试使用clock_gettime在C代码中计时,在调用GetArrayLength之后开始,在调用NewDoubleArray之前结束。@Ctx garbadge collector是否每500毫秒清理一次内存?
allocFFT(2048);
handler = new Handler();
runnable = new Runnable() {
@Override
public void run() {
short[] data = new short[2048];
for(short iter=0; iter<2048; ++iter)
data[iter] = iter;
Long lastTime = System.currentTimeMillis();
doFFT(data);
Log.i("fft",String.valueOf(System.currentTimeMillis()-lastTime));
handler.postDelayed(runnable,10);
}
};
handler.postDelayed(runnable,1000);
01-09 17:48:03.310 21976-21976/? I/fft: 4
01-09 17:48:03.370 21976-21976/? I/fft: 52
01-09 17:48:03.385 21976-21976/? I/fft: 2
01-09 17:48:03.400 21976-21976/? I/fft: 2
01-09 17:48:03.410 21976-21976/? I/fft: 1
01-09 17:48:03.425 21976-21976/? I/fft: 1
01-09 17:48:03.435 21976-21976/? I/fft: 2
01-09 17:48:03.450 21976-21976/? I/fft: 1
01-09 17:48:03.460 21976-21976/? I/fft: 1
01-09 17:48:03.475 21976-21976/? I/fft: 2
01-09 17:48:03.485 21976-21976/? I/fft: 2
01-09 17:48:03.495 21976-21976/? I/fft: 1
01-09 17:48:03.510 21976-21976/? I/fft: 1
01-09 17:48:03.520 21976-21976/? I/fft: 5
01-09 17:48:03.535 21976-21976/? I/fft: 4
01-09 17:48:03.555 21976-21976/? I/fft: 4
01-09 17:48:03.570 21976-21976/? I/fft: 5
01-09 17:48:03.585 21976-21976/? I/fft: 4
01-09 17:48:03.600 21976-21976/? I/fft: 4
01-09 17:48:03.615 21976-21976/? I/fft: 5
01-09 17:48:03.630 21976-21976/? I/fft: 4
01-09 17:48:03.645 21976-21976/? I/fft: 5
01-09 17:48:03.660 21976-21976/? I/fft: 4
01-09 17:48:03.675 21976-21976/? I/fft: 5
01-09 17:48:03.690 21976-21976/? I/fft: 4
01-09 17:48:03.705 21976-21976/? I/fft: 4
01-09 17:48:03.720 21976-21976/? I/fft: 5
01-09 17:48:03.785 21976-21976/? I/fft: 52
01-09 17:48:03.800 21976-21976/? I/fft: 5
01-09 17:48:03.815 21976-21976/? I/fft: 5
01-09 17:48:03.830 21976-21976/? I/fft: 4
01-09 17:48:03.850 21976-21976/? I/fft: 5