gpu / JOCL

Java bindings for OpenCL
http://www.jocl.org
Other
187 stars 33 forks source link

Port to Android Toolchain #4

Closed phlip9 closed 8 years ago

phlip9 commented 8 years ago

TODO: More general cross-compiling support?

TODO: Better, more explicit support for other OS's / ARCH's?

TODO: Library would be more accessible if uploaded to maven repo. But we also have native libraries which makes everything painful.

TODO: Refactor out native library loading to another library? There's lots of redundancy and slight changes between this LibUtils, jcuda's LibUtils, our LibUtils (BIDMat), etc...

gpu commented 8 years ago

Thanks for this contribution!

Actually, I created an Android version of JOCL ~4 years ago, but I had a non-disclosure-agreement with some company (which now does no longer seem to give a ... care about this topic - and the NDA was limited to 3 years, so ... the risk of being sued should be rather small). I remember that there had been some other issues. From the tip of my head, there was something related to the inheritance hierarchy of the Buffer class, but I'll have to revise this - it might be that this is no longer an issue.

I'll have to read through the changes in more detail. I'll try to do this during the weekend, and give it a try early next week (I should even be able to test it on some android device - the above mentioned company provided me one, and they never wanted it back...).

But quickly going over the changes and the points that you mentioned:


Regarding the TODOs:

Generalizations regarding the target platforms (and their build processes):

These are always welcome. However, they may increase the complexity of the makefiles considerably. (You might have noticed that the current issues in the issue tracker are related to "embarassingly basic" problems of building on other platforms - I hope that a robust, portable and maintainable solution can be found there soon...)


The native library deployment (and loading) is indeed an issue. There have been some related discussions in the JOCL forum. The migration of JOCL from "a downloadable ZIP" to "a Maven artifact" was a hassle. (For me, because I'm not a Maven expert, and ... native libraries are always difficult in Maven).

I'll try to summarize some points here (and consider to open one or more dedicated issues in the issue tracker for these) :

(BTW: I didn't even know BIDMat, thanks for this pointer)

phlip9 commented 8 years ago

Sizeof.computePointerSize(): The "sun.arch.data.model" string is, according to the name, likely just a "legacy" property and too specific. But according to https://docs.oracle.com/javase/tutorial/essential/environment/sysprop.html , System.getProperty("os.arch"); should be a portable approach, and I'd prefer this to a JNI based solution (if it works on Android as well).

I'm not sure this is always valid. While the system might be 64 bit, the library and/or JVM could be compiled as 32 bit. I'm not sure how exactly the "os.arch" responds to say a 32 bit vs 64 bit JVM or the precise interplay between JVM and native pointers; but (from my understanding, please correct me if I'm wrong), I would assume the native code interacting with the OpenCL API is the source of truth in this case.

LibInitializer.java : These hard-coded paths look a bit odd, but from a quick websearch, "trying out different names" seems to be the way to go here. (This might be related to the last TODO, see below)

I agree. It's definitely not pretty, but Google has not standardized OpenCL on Android (they're pushing for their own framework called Renderscript). As a result, every vendor seems to put their library in nonstandard locations...

Android shared library outputs to nativeLibraries/${ANDROID_ABI}/ : I'm not entirely sure (yet) what this is about (and have I'll have to revise how I handled the native library in my first tests). Usually, the intention in JOCL is to pack the native library into the JAR, unpack it at runtime, and load it with System.load. The System.loadLibrary path is mainly for local tests and as a fallback. However, there are some open questions, also regarding Maven and the deployment of the natives (also see the TODOs below)

Unfortunately, I don't think Android supports unpacking the library and then loading it (might have something to do with permissions?) Maybe I'm wrong, but I haven't had any luck with the extract and then load process. Android's loadLibrary method is nonstandard in that a call to loadLibrary("libfoo.so") searches not for lib/libfoo.so but rather lib/armveabi-v7a/libfoo.so and lib/arm/libfoo.so if, for example, the device is running an armv7a compatible processor. I would like a more standard and maintainable library loading method, however.

On a different note, I'm wondering whether we should classify Android as its own OS or put it under Linux in LibUtils. I'm not sure what the exact differences are, if any, between binaries compiled with the arm-linux-androideabi toolchain and the arm-linux-gnueabi toolchain.

gpu commented 8 years ago

I'm not sure this is always valid. While the system might be 64 bit, the library and/or JVM could be compiled as 32 bit. I'm not sure how exactly the "os.arch" responds to say a 32 bit vs 64 bit JVM or the precise interplay between JVM and native pointers; but (from my understanding, please correct me if I'm wrong), I would assume the native code interacting with the OpenCL API is the source of truth in this case.

On the one hand, you are right. According to a quick websearch, os.arch returns the JRE architecture, and not the OS architecture. On the other hand, this is kind of a chicken-egg problem: The native library that will be loaded will also depend on the os.arch. The alternative would thus be to store the bitness directly in the LibUtils.ArchType enums and obtain them from ther. But frankly, the ArchType involves some guesswork as well, so I think that obtaining this information natively (and generically) is at least reasonable - maybe I'll review this if the LibUtils are refactored.

Unfortunately, I don't think Android supports unpacking the library and then loading it ...

This may be true. I had another look at my old JOCL-Android project, and noticed the libs/armeabi and libs/armeabi-v7a directories there, containing the JOCL binaries. However, this project was set up years ago. It still used the Eclipse ADT plugin and custom .mk makefiles - and admittedly, I didn't investigate all the details that are hidden behind the convenient "Install" button that pushes the APK to the device...


Regarding the pull request: I had a closer look at this, and it seems that it is safe and compatible to the existing toolchains. I reviewed the changes, tested it locally, and everything worked fine. So I merged it locally, with minor adjustments, and will push it soon.

One thing: In https://github.com/gpu/JOCLCommon/pull/3 you added the -fPIC flag for Unix platforms. I think this is strongly related to https://github.com/gpu/JOCL/issues/3 . Might it be that this change also resolves the issue?


Apart from that, I'm currently updating (or rather reviving) my Android infrastructure: I downloaded Android Studio and try to familiarize with it, and see how the NDK interplays with it. I have some trouble with my android device (API version 7 ... ) : It's connected to the USB for 1 hour now, and still says "Charging: 0%" - hope it's not a defect battery... However, I hope that once everything is set up, I can actually try out your changes.

gpu commented 8 years ago

Forgot that one:

I'm wondering whether we should classify Android as its own OS or put it under Linux in LibUtils

Although it does not make a difference in the LibUtils, the difference in the LibInitializer is crucial: For Android, it needs the predefined implementation library paths. (This might also be reviewed during a refactoring of the LibUtils, but at the moment, the ANDROID type seems to be required)