在尝试了很多的方法后,终于可以在Android Studio上使用OpenCL,现在记录一下过程。
判断手机是否支持OpenCL的方法
- 下载aida64,在设备里查看是否有OpenCL设备
- 下载Opencl-z,如果支持,通过此软件可以查看到platform和device
在native-lib中使用Opencl
- git clone [email protected]:GaussRieman/libopencl-stub.git
- 在Android.mk中添加一个static library
include $(CLEAR VARS)
LOCAL_MODULE := libopenclstub
LOCAL_C_INCLUDES := path/to/libopencl-stub/include
LOCAL_SRC_FILES := path/to/libopencl.c
LOCAL_CFLAGS := -fPIC -o2
include $(BUILD_STATIC_LIBRARY)
- 在native-lib中添加对stub库的静态链接
LOCAL_STATIC_LIBRARIES += libopenclstub
- 在native-lib中添加对CL头文件的支持
LOCAL_C_INCLUDES += path/to/libopencl-stub/include/CL/
- 在cpp或c中包含CL头文件就可以使用了
有兴趣的深入一下,为什么要用stub
很多人会参考一篇文章,里面提到了这个原因,因为google是不公开支持opencl的,所以NDK中并不会有libOpenCL.so,这个库都是放在各个厂家的库中,比较常见的位置是"system/vendor/lib64/libOpenCL.so",但是如果你将这个库adb pull到host,然后作为一个动态库放到Android Studio中使用,在运行时会报错找不到“libc++.so”:
03-21 17:07:51.502 31234 31234 W linker : library "libandroid_runtime.so"
("/system/lib/libandroid_runtime.so") needed or dlopened by
"/data/app/com.popular-app.android-2/lib/arm/libapplib.so" is not accessible for the namespace "classloader-namespace" - the access is temporarily granted as a workaround for http://b/26394120
这是因为libOpenCL.so会调用libc++.so,以及libcutils.so,这些依赖可以通过下面的命令找到。
aarch64-linux-android-readelf -dW libOpenCL.so
根据参考的博客里面的方法,将所需的动态库全部pull出来,当做app的私有库来加载,的确可以解决编译的问题,但是在使用clGetPlatforms时,会找不到可用的platform。如果是开发一个底层库,在不知道vendor的情况下,只能将adrno, mali等GPU全部拷出来,一层层的依赖,甚至会涉及到libbase.so。。。不是一个好的办法。
另一种方式是上面提到的,使用stub,将libOpenCL.so动态加载,libopencl.c主要就是帮我们完成适配平台和封装接口的工作,它主要用到dlopen和dlsym,前者用来加载vendor支持的CL动态库,后者用来映射接口。
再扯一点题外话,google不支持OpenCL, Khronos小组也推出了Vulkan,所以CL地位很尴尬,目前在第三方库中使用OpenCL最好的就是使用stub,万一哪天google把dlopen也关了,那就真的没得玩了。。。