Использование OpenCL с Android JNI производит медленный код из-за некоторых накладных расходов - PullRequest
1 голос
/ 27 марта 2019

Я реализовал алгоритм на Android с использованием OpenCL и OpenMP. Реализация OpenMP работает примерно в 10 раз медленнее, чем реализация OpenCL.

  • 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 раз быстрее.


Идеи:

  • Возможно, графический процессор (в случае OpenCL) в целом менее эффективен, поскольку у него меньше доступной памяти. Есть несколько переменных, которые нам нужно предварительно выделить, которые используются в каждом кадре. Итак, мы проверили время, которое требуется Android для рисования растрового изображения в обоих случаях (OpenMP, OpenCL). В случае OpenCL иногда рисование растрового изображения занимало больше времени (в 3 раза больше), но не на величину, которая бы выровняла общее время выполнения программы.

  • Использует ли JNI графический процессор для ускорения некоторых вызовов, что может привести к замедлению версии OpenCL?

EDIT:

  • Возможно ли, что сборка мусора Java запускается OpenCL, вызывая большие накладные расходы?

1 Ответ

0 голосов
/ 03 апреля 2019

Оказывается, часы () ненадежны (на 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);

Это было предложено здесь: Как получить время вычисления в NDK

...