Using OpenCL in the new Android Studio

Issue

I am attempting to write a short application that uses OpenCL 1.2 (not for distribution, so universal access is not an issue) to do a computation. However, OpenCL is giving me a bit of trouble on Android. I have, on my computer, the libopencl.so file and the 1.2 headers from the AMD SDK. The question is: how do I properly use them?

Where in the gradle (newest version) build file do I specify this, or can someone recommend a good place for me to turn to to read up on this? Or, what do I need to understand theoretically for me to figure out on my own – what is required to properly link to the OpenCL libraries?

I’ve already tried the answer mentioned here:
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")
    }
}

Thanks

Solution

It is quite complicated process. I will try to keep it concise.

  1. To run your app on Android, libopencl.so from AMD will not work. The OpenCL library must be compatible with your device. For Android armv7 device, you need a OpenCL library provided by the chip vendor, and compiled with armv7 toolchain. To run on Intel Atom device, you need the library to be provided by the chip vendor and was compiled targeting to x86_32 arch.

Basically, for your question, You have two ways to go:

[Method 1] grab the libOpenCL.so or libGLES_mali.so, or libPVROCL.so from devices you have. The above lib names correspond to Adreno, Mali and PowerVR GPUs. Use those libraries to compile your code.

[Method 2] In your native code, open the OpenCL library using dlopen, then using dlsym to map the clBlaBla APIs to your own name. For example, you can map clGetDeviceInfo to myCLGetDeviceInfo. Then, in your own native code, you can call myClGetDeviceInfo instead. This way requires you know the path to the opencl library on your devices. For example, on Adreno GPUs, the location will be /system/vendor/lib/libOpenCL.so. For more details, read another post. Does Android support OpenCL?

Method 2 is more general and elegant. Method 1 is simpler, and quicker if you clearly know what devices your app will run on. For example, if you clearly know your app is only for testing on adreno gpus, then you can simply grab libOpenCL.so from your test device. Then use it to link your app. This link shows how to do this, and provides an sample code. You can start from there.

In terms of using Android studio. I can only comment this: if you understand the requirement of compiling an OpenCL app on Android. Compiling using Android studio or directly using ndk-build have no difference. The syntax can be one-to-one mapped from one to another.

For my personal experience, I wrote a lot of Android.mk files, and I am getting used to it. So even if now I use Android Studio to develop. The method in the article you linked is actually correct.

However, I still use ndk-build to compile my native code, as usual. That way, I can have full control on what happened there, and I feel more comfortable. Once I got the .so native library, I put it into the jniLibs folder under src/main (your folder structure could be different). jniLibs is the default folder where the Android studio will locate the native libraries. You can also specify your own folder in the gradle script (tons of articles online, search gradle ndk). Of course, all the above operations are done by a script (ndk-build, copy the library to some folder). Once I have all these, I build the app using Android studio. Typically, you wont debug the JAVA code and change native code at the same time, so doing the above is totally OK and quite comfortable. If you want to automate all these, you can ask the gradle to launch the ndk build script you wrote before it builds the app. Or you can ask the gradle to run ndk-build command the way you like (this is actually used by a lot of developer).

Hope this is helpful. Any further discussion is welcome.

Answered By – Robert Wang

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published