在新 Android Studio 中使用 OpenCL

Using OpenCL in the new Android Studio

我正在尝试编写一个使用 OpenCL 1.2(不用于分发,因此通用访问不是问题)进行计算的简短应用程序。但是,OpenCL 在 Android 上给我带来了一些麻烦。我的计算机上有 libopencl.so 文件和来自 AMD SDK 的 1.2 headers。问题是:我该如何正确使用它们?

我在 gradle(最新版本)构建文件的哪个位置指定了这个,或者有人可以推荐一个好地方让我转向阅读这个吗?或者,我需要从理论上了解什么才能自己弄清楚 - 正确 link 到 OpenCL 库需要什么?

我已经尝试过这里提到的答案:

apply plugin: 'com.android.model.application'

model {
    android {
        compileSdkVersion = 21
        buildToolsVersion ="22.0.1"

        defaultConfig.with {
            applicationId = "com.example.thing"
            minSdkVersion.apiLevel = 14
            targetSdkVersion.apiLevel = 14
        }
    }
    /*
     * native build settings
     */
    android.ndk {
        moduleName = "otherThing"

        ldLibs += "log"
        ldLibs += "android"
        //cFlags "~/OpenCL1-2HeaderFiles"
    }
    android.buildTypes {
        release {
            isMinifyEnabled = false
            proguardFiles  += file('proguard-rules.txt')
        }
    }

    android.productFlavors {
        create("arm") {
            ndk.abiFilters += "armeabi"
        }
        create("arm7") {
            ndk.abiFilters += "armeabi-v7a"
        }
        create("arm8") {
            ndk.abiFilters += "arm64-v8a"
        }
        create("x86") {
            ndk.abiFilters += "x86"
        }
        create("x86-64") {
            ndk.abiFilters += "x86_64"
        }
        create("mips") {
            ndk.abiFilters += "mips"
        }
        create("mips-64") {
            ndk.abiFilters += "mips64"
        }
        create("all")
    }
}

谢谢

这是一个相当复杂的过程。我会尽量保持简洁。

  1. 至 运行 您在 Android 上的应用程序,来自 AMD 的 libopencl.so 将无法运行。 OpenCL 库必须与您的设备兼容。对于 Android armv7 设备,您需要芯片供应商提供的 OpenCL 库,并使用 armv7 工具链编译。要在 Intel Atom 设备上 运行,您需要由芯片供应商提供的库,并针对 x86_32 arch 进行编译。

基本上,对于你的问题,你有两种方法:

[方法 1] 从您拥有的设备中获取 libOpenCL.so 或 libGLES_mali.so,或 libPVROCL.so。以上库名称分别对应 Adreno、Mali 和 PowerVR GPU。使用这些库来编译您的代码。

[方法 2] 在您的本机代码中,使用 dlopen 打开 OpenCL 库,然后使用 dlsym 将 clBlaBla API 映射到您自己的名称。例如,您可以将 clGetDeviceInfo 映射到 myCLGetDeviceInfo。然后,在您自己的本机代码中,您可以改为调用 myClGetDeviceInfo。这种方式要求您知道设备上 opencl 库的路径。例如,在 Adreno GPU 上,位置将为 /system/vendor/lib/libOpenCL.so。有关更多详细信息,请阅读另一篇 post。 Does Android support OpenCL?

方法2更通用也更优雅。如果您清楚地知道您的应用程序将 运行 在哪些设备上运行,则方法 1 更简单、更快捷。例如,如果您清楚地知道您的应用仅用于在 adreno gpus 上进行测试,那么您可以简单地从您的测试设备中获取 libOpenCL.so。然后将其用于 link 您的应用。此 link 展示了如何执行此操作,并提供了示例代码。你可以从那里开始。

在使用 Android 工作室方面。我只能对此发表评论:如果您了解在 Android 上编译 OpenCL 应用程序的要求。使用 Android studio 编译或直接使用 ndk-build 编译没有区别。语法可以一对一地从一个映射到另一个。

个人经验,写了很多Android.mk个文件,慢慢习惯了。所以就算现在我用Android Studio来开发。您link阅读的文章中的方法实际上是正确的。

但是,我仍然像往常一样使用 ndk-build 来编译我的本机代码。那样的话,我可以完全控制那里发生的事情,而且我感觉更舒服。获得 .so 本机库后,我将其放入 src/main 下的 jniLibs 文件夹中(您的文件夹结构可能不同)。 jniLibs 是 Android 工作室将在其中放置本机库的默认文件夹。也可以在gradle脚本中指定自己的文件夹(网上文章一大堆,搜索gradlendk)。当然,以上所有操作都是通过一个脚本完成的(ndk-build,将库复制到某个文件夹)。一旦我拥有所有这些,我就使用 Android studio 构建应用程序。通常情况下,您不会同时调试 JAVA 代码和更改本机代码,因此执行上述操作完全可以并且很舒服。如果你想自动化所有这些,你可以要求 gradle 启动你在构建应用程序之前编写的 ndk 构建脚本。或者你可以按照你喜欢的方式询问 gradle 到 运行 ndk-build 命令(这实际上被很多开发人员使用)。

希望这对您有所帮助。欢迎进一步讨论。

非常感谢您的回复,罗伯特!我需要让一些东西工作,所以我最终做的是通过检查

来检查安装它的设备
static const char *default_so_paths[] = { // Android
                                            "/system/lib/libOpenCL.so", "/system/vendor/lib/libOpenCL.so",
                                            "/system/vendor/lib/egl/libGLES_mali.so",
                                            "/system/vendor/lib/libPVROCL.so",
                                            "/data/data/org.pocl.libs/files/lib/libpocl.so",
                                          // Linux
                                            "/usr/lib/libOpenCL.so",            "/usr/local/lib/libOpenCL.so",
                                            "/usr/local/lib/libpocl.so",
                                            "/usr/lib64/libOpenCL.so", "/usr/lib32/libOpenCL.so",
                                            "libOpenCL.so"
                                          };

然后映射 API,我想我一定是在某个时候看到了如何做。

我终于开始工作了,但我想感谢您的全面回复,以及您在本论坛上关于此主题的大部分回复。他们都非常有帮助。