在新版Android Studio中使用OpenCL

3
我正在尝试编写一个短应用程序,使用OpenCL 1.2(不用于分发,因此通用访问不是问题)进行计算。然而,在Android上使用OpenCL有些麻烦。我在我的电脑上有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,因此您需要加载这些库。 - DarkZeros
3个回答

3
非常感谢您的回复,Robert!我需要让某些东西起作用,所以最终我做的是通过检查安装它的设备来进行处理。
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,我想我以前肯定见过如何做。

终于让事情顺利起来了,但我还是想感谢你,不仅仅是因为这个详细的回复,而且是关于这个主题的你在���个论坛里的大部分回复都非常有帮助。


1
这实际上是一种更好的适用于Android的OpenCL编程方式。很高兴看到您以这种方式使其工作。这实际上使得您的程序可以更轻松地进行编译/链接,特别是如果您想支持尽可能多的GPU。 - Robert Wang

3
这是一个相当复杂的过程。我会尝试简明扼要地说明。
1. 要在Android上运行你的应用程序,来自AMD的libopencl.so将不起作用。OpenCL库必须与你的设备兼容。对于Android armv7设备,你需要由芯片供应商提供的,并使用armv7工具链编译的OpenCL库。对于Intel Atom设备,你需要由芯片供应商提供的库,并针对x86_32架构进行编译。
2. 对于你的问题,基本有两种解决方法:
[方法1] 从你拥有的设备中获取libOpenCL.so或libGLES_mali.so,或libPVROCL.so。上述库名称分别对应Adreno、Mali和PowerVR GPU。使用这些库来编译你的代码。
[方法2] 在你的native代码中,使用dlopen打开OpenCL库,然后使用dlsym将clBlaBla API映射到你自己的名称。例如,你可以将clGetDeviceInfo映射到myCLGetDeviceInfo。然后,在你自己的native代码中,你就可以调用myClGetDeviceInfo了。这种方法需要你知道设备上opencl库的路径。例如,在Adreno GPU上,位置将为/system/vendor/lib/libOpenCL.so。更多细节请参见Does Android support OpenCL? 方法2更通用、更优雅。方法1更简单,如果你清楚知道你的应用程序将在哪些设备上运行,它会更快。例如,如果你清楚知道你的应用程序只是用于在Adreno GPU上进行测试,那么你可以直接从测试设备中获取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命令(实际上被许多开发人员使用)。
希望这对您有所帮助。欢迎进一步讨论。

非常感谢您的回复,Robert!我需要让某些东西工作起来,所以我放弃了Android Studio,转而使用Eclipse。 - markymark
使用方法2时,如何调用atan2函数? - RonTLV
atan2函数是内核函数,属于OpenCL C语言。上面讨论的方法与主机函数(OpenCL API函数)有关。无论使用哪种方法,只要设备支持OpenCL,atan2函数就应该存在。 - Robert Wang

2
Caused by: java.lang.IllegalArgumentException: Internal error: Failed to apply delegate: Can not open OpenCL library on this device - dlopen failed: library "libOpenCL.so" not found
    Falling back to OpenGL
    TfLiteGpuDelegate Init: No shader implementation for reduce_maximum
    TfLiteGpuDelegate Prepare: delegate is not initialized

For this error it can be fixed by writing in application AndroidManifest.xml :::
        <uses-native-library
        android:name="libOpenCL.so"
        android:required="false" />

尽管这条注释格式不规范,但它仍然有效,谢谢! - Filipp Maksimov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接