【问题标题】:Using OpenCL in the new Android Studio在新的 Android Studio 中使用 OpenCL
【发布时间】:2015-10-15 04:48:57
【问题描述】:

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

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

我已经尝试过这里提到的答案: Android Studio fatal error: CL/cl.h No such file or directory

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")
    }
}

谢谢

【问题讨论】:

  • 因为 Android 和 OpenCL 并不是真正的好朋友(感谢 google 偏爱 RenderScript)。我建议您使用非库实现,使用 CLEW 作为基础,并从设备动态加载 .lib。在某些设备中,OpenCL 位于 libGLES_MALI.so 等其他库中,因此您需要加载它们。

标签: android android-studio opencl android-gradle-plugin build.gradle


【解决方案1】:

非常感谢您的回复,罗伯特!我需要让某些东西正常工作,所以我最终做的是通过检查来检查安装它的设备

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,我想我之前一定看过如何做。

我终于把事情搞定了,但我想感谢你的全面回复,以及你在这个论坛上关于这个主题的大部分回复。他们都非常有帮助。

【讨论】:

  • 这实际上是一种更好的 Android OpenCL 编程方式。很高兴看到你让它以这种方式工作。这实际上可以让您的程序更容易编译/链接,特别是如果您想支持尽可能多的 GPU。
【解决方案2】:

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

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

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

[方法 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。有关更多详细信息,请阅读另一篇文章。 Does Android support OpenCL?

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

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

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

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

希望这会有所帮助。欢迎任何进一步的讨论。

【讨论】:

  • 非常感谢您的回复,罗伯特!我需要一些工作,所以我放弃了 Android Studio,转而使用 Eclipse。
  • 使用方法二时,如何调用atan2函数?
  • atan2函数是内核函数,属于OpenCL C语言。上面讨论的方法与主机函数(OpenCL API 函数)有关。无论你使用哪种方法,如果设备支持 OpenCL,atan2 func 应该在那里。
猜你喜欢
  • 1970-01-01
  • 2018-07-15
  • 1970-01-01
  • 2016-02-04
  • 2018-05-24
  • 2014-07-25
  • 2017-12-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多