Giter Club home page Giter Club logo

Comments (10)

saudet avatar saudet commented on July 3, 2024

Glad to hear it's working well :)

I'm not sure how they are making this work from C, but maybe it works the same from Java. Can you try to call something like System.loadLibrary("atlas") or System.load("/path/to/libatlas.so") before trying to use GSL?

from javacpp-presets.

saudet avatar saudet commented on July 3, 2024

No, this isn't going to work. I see that we need to relink the libjnigsl.so file. The easiest way to go about this is by modifying the Java config file and rebuild the JAR file. On Linux, Mac OS X, or other Unix variants, make a change like this in the presets/gsl.java file:

- link={"[email protected]", "[email protected]"}),
+ link={"[email protected]", "[email protected]", "[email protected]"}, linkpath={"/usr/lib/atlas/", "/usr/lib64/atlas/"}),

And rebuild by calling bash cppbuild.sh install gsl and mvn install --projects gsl. It's possible to skip the cppbuild phase and use the GSL library installed on the system. In that case, we would need to add the includepath and linkpath along the ones for ATLAS above, but that's it. I'm not sure if there would be an easier way to make all this work out of the box... Should we package GSL with ATLAS by default?

BTW, are there any other C/C++ libraries that you would like to use or are using from Java? They might be good candidates to add to this project :) Thanks for the feedback

from javacpp-presets.

blueberry avatar blueberry commented on July 3, 2024

Hi, thanks for the help.

Regarding atlas, it is pointless to bundle it with the jar because the whole point of atlas is to build it and fine tune it for a specific processor architecture.

I had to change plans and build my own java blas wrapper because gsl is gpl, so I am not allowed to mix it with Clojure libraries, which are usually EPL license.

Ideas for native libraries? I tend to think that cblas and lapacke would be good candidates, since Java still sucks at number crunching.
However, currently I have to resort to hand-written JNI because it is important to me to avoid copying arrays from jvm->native code and it seems that all autogenerated libraries do the copying. I need GetPrimitiveArrayCritical :)

Still, I am very impressed by javacpp - excellent performance :)

from javacpp-presets.

saudet avatar saudet commented on July 3, 2024

I see, thanks for the feedback! BTW, we could easily wrap CBLAS and LAPACK with JavaCPP:
https://github.com/bytedeco/javacpp-presets/wiki/Create-New-Presets
And GetPrimitiveArrayCritical() does get used on arrays.

from javacpp-presets.

saudet avatar saudet commented on July 3, 2024

Oh wait, you need to use GetPrimitiveArrayCritical() on all function calls? JavaCPP doesn't do that, no, because the JDK doesn't recommend it, and says it might not even do what we want it to do anyway:
http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/functions.html#GetPrimitiveArrayCritical

When we're after performance, we should be using direct NIO buffers. Those are as fast as arrays inside both Java and in native code with JNI, and are well supported by the JDK in general.

from javacpp-presets.

blueberry avatar blueberry commented on July 3, 2024

I use the critical version on all arrays. It MIGHT return a copy, but in my (preliminary and simple, but run millions of times) tests it never did. On the other hand, the non-critical version always returned a copy.

I heard different kinds of stories about critical vs. buffer. Only anecdotal, without an example or demonstration, and without the any link to detailed discussion. I cannot find any part in the docs where critical call is not recommended or discouraged. There are only constraints, which are fine for my use case. fommil (netlib-java), who has similar use case, also uses critical calls for the project, and he did not have any problems.

I am still quite open to NIO, but that also have drawbacks - unnatural API. Instead of methods that take arrays, there would be bytebuffers all the way.

I am puzzled by another thing. In all java libs that I tried, even the simplest JNI call with primitive arguments took several time longer than a simple calculation JNI hello world. For example, javacpp-gsl call to logarithm function took, if I remember well, 25 ns (measured by the criterium library). The call to hello takes 8 ns. Where do 17 ns go? Even java's Math.log takes 2 ns or so, so I expect gsl log to be similar.
The same goes for other autogenerated wrappers - they take much more time than the handwritten versions that I rushed in an hour. One obvious reason would be that they copy arrays everywhere, but If they don't, what else could be the reason for the overhead? All those libraries are autogenerated, so finding the reason is not that simple as looking at the code, and I didn't pursue it further.

I understand that nanoseconds are not that important for the majority of software, but for the building blocks of numerical code that is a considerable waste that multiplies quickly ;)

from javacpp-presets.

saudet avatar saudet commented on July 3, 2024

In the link above they say "After calling GetPrimitiveArrayCritical, the native code should not run for an extended period of time before it calls ReleasePrimitiveArrayCritical." That sounds like a big fat warning to me. But if everything works fine in your application, that's fine I suppose. I'm just not sure what the advantages are over direct NIO buffers. I don't find calling get() and put() to be any more unnatural than brackets and equal signs :) Besides, I've implemented that way efficient multidimensional arrays from a contiguous block of memory, something that we can't do with Java arrays directly anyway:
bytedeco/javacpp@4d8dc9d

There are a few places where the overhead might come from. In this case, I think the largest overhead would come from checking for C++ exceptions, but we'd have to check the generated code to make sure. We can disable checking for C++ exceptions with the @NoException annotation, but the Parser doesn't do that automatically right now, because like you say it's not something that most people look into. But it is possible to optimize everything to make it as fast as handwritten JNI if necessary.

from javacpp-presets.

blueberry avatar blueberry commented on July 3, 2024

One source for the complexity might be that autogen libraries try to cover C++, which is very complex, and they have to deal with many edge cases, whereas when I choose plain C there are less of those things to consider, and also I can choose what applies in my use case.
Of course, the tool may provide different switches and settings, but then plain JNI code suddenly becomes simpler :)
All in all, my current (limited) experience with JNI is that it is not too much complex, it only has more boilerplate than Java, and I had to learn a few tools from the C ecosystem...

from javacpp-presets.

saudet avatar saudet commented on July 3, 2024

Of course if you know exactly what you're doing, it's better to code everything in C, and a bit of JNI isn't going to change a whole lot. But the point of developing with Java is usually because we don't know exactly what we're doing. We build prototypes, try stuff out, debug the hell out of everything, etc, and the better the tools we have for those tasks, the more time we can spend on the essential.

For example, let's assume that we need to call the logarithm function on only one scalar very often. With the Java wrappers, we could start experimenting with that, and make sure that our algorithm works well. Then, when we know that everything is fine, but that it has become the bottleneck of our application, we make a new function in C/C++, and call that function from Java. And JavaCPP can still help here in calling that new function by abstracting the differences between platforms, and by maintaining compatibility with the rest of the native functions without effort.

from javacpp-presets.

saudet avatar saudet commented on July 3, 2024

It's been a while, but with the commit above, presets for GSL now link automatically with OpenBLAS, MKL, Accelerate, etc instead of GSL CBLAS, and they do not try to catch C++ exceptions anymore, so they should be pretty much as fast as manually written JNI wrapper code.

from javacpp-presets.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.