从Java运行C代码和从纯C运行C代码之间的区别

时间:2017-01-09 15:06:20

标签: java c performance java-native-interface

我必须在我的android项目中使用DFFT。我找到了kissfft库并决定使用它。

我已经按如下方式编写了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 /* 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,&amps[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);
}

然后在MyActivity类中,我确实如下:

 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

正如你所看到的,fft计算的时间有时看起来很奇怪 - 它是否比平均值大10倍。

我尝试在纯C中使用相同的库进行相同的测试,并且没有这样的结果 - 所有计算时间大致相等。

因此,假设问题出现在我的本机代码中是合乎逻辑的,可能我忘了做重要的事情,我不知道。请帮帮我。

0 个答案:

没有答案