【发布时间】:2019-08-18 10:25:55
【问题描述】:
我使用 OpenCL 和 OpenMP 在 android 上实现了一个算法。 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 情况下)通常效率较低,因为它的可用内存较少。我们需要预先分配的变量很少,每帧都会使用这些变量。因此,我们检查了 android 在两种情况下(OpenMP、OpenCL)绘制位图所需的时间。在 OpenCL 的情况下,有时绘制位图需要更长的时间(3 倍),但不会达到使程序的整体运行时间相等的量。
JNI 是否使用 GPU 来加速某些调用,这可能会导致 OpenCL 版本变慢?
编辑:
- 会不会是 OpenCL 触发了 Java 垃圾回收,导致开销很大?
【问题讨论】:
-
您在哪个设备/操作系统上进行了测试。另外您使用的是哪个版本的 OpenMP 库(32 位/64 位)?
-
我在 Open-Q 820 μSOM 上进行了测试。 OpenMP 在这里并不重要,因为问题在于 OpenCL 很慢。
-
"使用 OpenCL,我们需要在其上分配一些变量,这些变量在每一帧中都使用" - 我不确定您所说的“变量”是什么意思,但如果您正在分配和发布新的每一帧都有缓冲区,你几乎肯定做错了。我的方法是将缓冲区作为静态变量(“cl_mem”类型),并添加两个方法“init”和“teardown”(不言自明)。然后只需在每帧渲染中通过静态变量使用这些缓冲区。这同样适用于 OpenCL 命令队列——不要每帧都创建和销毁它们;它可能很慢。您希望尽可能多地重用 CL 对象。
-
不,我们显然不会每帧都创建变量。
标签: android performance java-native-interface opencl