由于某些开销,将OpenCL与Android JNI一起使用会产生缓慢的代码

时间:2019-03-27 18:28:43

标签: android performance java-native-interface opencl

我在Android上使用OpenCL和OpenMP实现了一种算法。 OpenMP实现的运行速度比OpenCL慢10倍。

  • OpenMP:〜250毫秒
  • OpenCL:〜25毫秒

但是总的来说,如果我从Java android方面衡量时间,我得到的调用时间和获取值的时间大致相同。

例如:

  • Java代码:

    // calls C implementation using JNI (Java Native Interface)
    bool useOpenCL = true;
    myFunction(bitmap, useOpenCL); // ~300 ms, timed with System.nanoTime() here, but omitted code for clarity
    myFunction(bitmap, !useOpenCL); // ~300 ms, timed with System.nanoTime() here, but omitted code for clarity    
    
  • C代码:

    JNIEXPORT void JNICALL Java_com_xxxxx_myFunctionNative(JNIEnv * env, jobject obj, jobject pBitmap, jboolean useOpenCL)
    {
    // same before, setting some variables
    
    clock_t startTimer, stopTimer;
    startTimer = clock();
    if ((bool) useOpenCL) {
       calculateUsingOpenCL(); // runs in ~25 ms, timed here, using clock()
    }
    else {
       calculateUsingOpenMP(); // runs in ~250 ms
    }
    stopTimer = clock();
    __android_log_print(ANDROID_LOG_VERBOSE, APPNAME, "Time in ms: %f\n", 1000.0f* (float)(stopTimer - startTimer) / (float)CLOCKS_PER_SEC);
    
    // same from here on, e.g.: copying values to java side
    }
    

在两种情况下,Java代码都大致同时执行,大约300毫秒。更准确地说,elapsedTime对于OpenCL来说要多一些,也就是说,OpenCL平均来说要慢一些。

考虑到OpenMP的各个运行时以及OpenCL的实现,OpenCL版本总体上应该要快得多。但是由于某种原因,我无法找到开销。

我还比较了OpenCL与普通本机代码(无OpenMP),尽管calculateUsingOpenCL的运行速度至少快了10倍,但我仍得到相同的结果,总体运行时大致相同。


想法:

  • 也许GPU(在OpenCL情况下)通常效率较低,因为它具有较少的可用内存。我们几乎不需要预分配变量,这些变量在每个帧中都会使用。因此,我们检查了两种情况(OpenMP,OpenCL)下android绘制位图所花费的时间。在OpenCL的情况下,有时绘制位图会花费更长的时间(更长的3倍),但是所花的时间并不能等于程序的整体运行时间。

  • JNI是否使用GPU来加速某些调用,这可能会导致OpenCL版本变慢?

编辑:

  • Java垃圾回收是否可能由OpenCL触发,从而导致大量的开销?

1 个答案:

答案 0 :(得分:0)

事实证明,clock()是不可靠的(在Android上),因此我们使用以下方法来测量时间。使用这种方法,一切正常。

int64_t getTimeNsec() {
    struct timespec now;
    clock_gettime(CLOCK_MONOTONIC, &now);
    return (int64_t) now.tv_sec*1000000000LL + now.tv_nsec;
}

clock_t startTimer, stopTimer;
startTimer = getTimeNsec();
    function_to_measure();
stopTimer = getTimeNsec();
__android_log_print(ANDROID_LOG_VERBOSE, APPNAME, "Runtime in milliseconds (ms): %f", (float)(stopTimer - startTimer) / 1000000.0f);

这是在这里建议的: How to obtain computation time in NDK