Building CUDA bindings for Windows with jextract

Marco Hutter panama at jcuda.org
Mon Feb 18 19:50:02 UTC 2019


Am 18.02.2019 um 19:35 schrieb Maurizio Cimadamore:
> Is this an issue (as in 'bug') or is this just a note on how to read 
> the jextract command line above? Is there an alternate command line 
> that you would have liked better but that doesn't work?

Not a "bug", for course, just for people who might wonder or want to try 
it out on a different OS.
E.g. on Linux, the default path for CUDA 10 is "/usr/local/cuda-10.0"



> Yep - System.loadLibrary has two modes:
>
> 1) library name -> as in "cublas" this would be expanded into a shared 
> library name - e.g. on linux libcublas.so
> 2) full absolute path to lib

To my understanding, System#loadLibrary uses the library name and does 
the prefix/suffix magic and scans the java.library.path for that lib. In 
contrast to that, System#load (without 'Library') takes the full path.
But sure, in both cases, the names have to match, so this is also not an 
issue with Panama. Just something to keep in mind for people who want to 
use it. (Maybe I'll set up a README.md somewhere, summarizing some of 
these points).



> The main issue here is what we have been calling 'library-centric' 
> approach - that is, instead of generating many separate classes - 
> generate a single root class which has all the required member 
> functions (the ones that appear in the shared library), and have all 
> required dependencies added in as inner classes. That would indicate 
> more clearly where you have to  look for.
>
> Note also that, for the purpose of looking inside classes (w/o using a 
> jar) you can also use jextract with "-d <dirname>" and output classes 
> into a folder, uncompressed.

Even if there are class files: Some of the CUDA-based libraries contain 
 >4000 functions, some of them taking 30 parameters. Generating even 
"empty" JavaDocs just to be able to easily browse through the API could 
be helpful. (Not an issue of jextract either, though. Using a decompiler 
was fine for me.)


> The long term solution would be the ability to reuse jextract runs by 
> pointing jextract at a previous extracted library.
>
> That said, I believe you should be able to extract all three libraries 
> in a single shot, by giving the three headers as input to jextract 
> (and the three libraries...); that will generate only one version of 
> everything. I used this approach for OpenGL which also relies on a 
> number of dependent headers - and generated a single jar.

For the first, basic tests, one could pack all libraries into one. But 
in terms of modularity (and proper package names), having the option to 
declare already generated dependencies would be favorable. I also think 
about the case where new libraries are published later. (This was the 
case for CUDA, but certainly for other libraries as well).
I don't have the slightest idea of how jextract works internally 
(although I went through some related issues, probably: Some of the 
JCuda code is auto-generated, and I'm using the Eclipse CDT to 
internally parse the header files into an AST, from which some of the 
JNI-bindings are generated). But I could imagine that is is tricky to 
figure out the required "mapping" between existing headers/JARs, and the 
headers that are included by others. In fact, this can become 
arbitrarily complicated (or even impossible) when the preprocessor comes 
into play...


> Again, I believe this situation will be much improved when we'll move 
> from an header-centric view (which of course expose all levels of 
> brittleness) towards a more library-centric view of the extraction 
> process.

I'm not entirely sure whether I understood this correctly. It sounds 
like the move to the "library-centric" approach was on the agenda...?
And wouldn't that mean that for headers like
     exampleDataType.h
     libA.h (including exampleDataType.h)
     libB.h (also including exampleDataType.h)
the class structure would be roughly like this:
     class LibA {
         private static class ExampleDataType {}
     }
     class LibB {
         private static class ExampleDataType {}
     }
making both "ExampleDataType" bindings be different types, and thus 
incompatible?

(BTW: If any of my dumb questions has already been discussed, you can 
ignore them (or maybe point me to the respective thread))


> enums are currently translated away as annotations - Java enums are 
> not an option because in C enums are much closer to ints than to Java 
> enums.
>
> That said, the current translation scheme could be improved at least 
> by grouping the methods of the enum constants under a common interface 
> (which can also define the annotation). That would make it easier to 
> see which constants are defined by an enum.
>
> This looks like a bug or something that can be improved.

Yes, sorry, I overlooked this: There is one header ("driver_types.h") 
that declares several enums, and it is translated into a "driver_types" 
interface. The enums are translated into annotations, as inner types. 
But the interface also offers methods for obtaining the constant values 
for ALL enums from this file. So the main point, namely having a way to 
access the constants, is solved. Having them grouped as in 
"enumName.methodForConstantX()" would be nice, though.



> Well, yes - accessing non DRAM memory via Unsafe is bound to fail in 
> mysterious ways. I'm less positive than you are re. gracefulness, in 
> the sense that I don't know under which condition the VM is able to 
> recover after a bad Unsafe::put/get. I would expect the mileage might 
> vary here - but I'm no VM engineer and I'll leave this specific point 
> to others.

Indeed, the details for different (mis-) usage scenarios will depend on 
OS, libraries, drivers etc. I just wanted to point out that this is 
something that can easily happen accidentally with CUDA, and the VM 
managed to recover at least in my first test.

bye
Marco





More information about the panama-dev mailing list