previous post
And yeah made another version for Java Numerations(JNum).
A lot has changed and I want you guys help now. JNum is now performant and comparable traditional OpenBlas/LAPACK bindings like ND4J and Numpy.
Benchmarks and features are in detailed in my github release but for lazy guys like me here are some data points worth see:-
-> JNum is feature rich(at least from previous version) where we have statistics jnum.stat IO operations jnum.io and basic Neural Networks jnum.nn.
-> JNum's IO will help you parse files like .npy/.npz , .csv/.tsv and most importantly .safetensorwhich Java lagging in this AI era.
-> We also have AsyncIO using Virtual Threads which make IO file reads faster in JNum.
-> jnum.statmodule has various statistic methods which Java community can use like standard deviations, variance , co-variance, cummulative sum/product, percentile etc.
-> JNum has slicing and subviewing features. Since we use NDArrays our operations can be chained together.
-> Most engineered parts are Matrix multiplication, Expression engine and Kotlin DSL. Since this is java subreddit i will go with first two parts.
- Matrix multiplication
in detail see my docs
But in short this is our benchmarks for matmul:
| Matrix Dimensions |
JNum (Pure Java 25) |
NumPy (C / OpenBLAS) |
ND4J (OpenBLAS C++) |
EJML (Pure Java) |
Performance Highlights |
| $4 times 4$ |
0.0002 ms |
0.0023 ms |
0.020 ms |
≈ 0.0001 ms |
11× faster than NumPy, 100× faster than ND4J |
| $16 times 16$ |
0.0004 ms |
0.0028 ms |
0.019 ms |
0.003 ms |
7× faster than NumPy, 47× faster than ND4J |
| $64 times 64$ |
0.015 ms |
0.013 ms |
0.190 ms |
0.140 ms |
On-par with NumPy, 9.3× faster than EJML |
| $128 times 128$ |
0.138 ms |
0.254 ms |
0.499 ms |
1.028 ms |
1.8× faster than NumPy, 7.4× faster than EJML |
| $512 times 512$ |
2.50 ms |
1.86 ms |
2.67 ms |
27.16 ms |
Matches C++ BLAS, 10.8× faster than EJML |
| $1024 times 1024$ |
13.85 ms |
8.98 ms |
12.18 ms |
216.56 ms |
Near-native speed, 15.6× faster than EJML |
| $2048 times 2048$ |
94.62 ms |
62.99 ms |
85.29 ms |
2,049.86 ms |
Pure Java competitive with C BLAS, 21.6× faster than EJML |
| $4096 times 4096$ |
942.38 ms |
487.92 ms |
857.41 ms |
17,419.52 ms |
Matches ND4J C++, 18.4× faster than EJML |
| $8192 times 8192$ |
6,784.15 ms |
5,967.30 ms |
6,317.97 ms |
141,500.0 ms |
~88% of NumPy C BLAS, 20.8× faster than EJML |
- Expression Engine
Basic engine for now but if some one gets fatigue of writing a.add().mul().div()... the we have JNum.eval() which is a literal AST running on shunting yard algorithm. Better than chaining but I would still recommend in place for better performance.
Kotlin devs can skip this because of DSL operator overloading.
Linear Algebra:-
we have various Linear Algebra methods which have performance on par sometimes beating Numpy
| Operation |
JNum (Pure Java 25) |
NumPy |
EJML |
ND4J |
JNum Advantage |
| Matrix Inverse |
7.271 ms |
10.680 ms |
18.122 ms |
1,224.654 ms |
1.47× faster than NumPy, 2.5× faster than EJML, 168× faster than ND4J |
| Linear Solve ($Ax=b$) |
1.976 ms |
1.003 ms |
5.331 ms |
37.278 ms |
Near-native speed, 2.7× faster than EJML, 18.8× faster than ND4J |
| Determinant |
1.839 ms |
5.735 ms |
5.380 ms |
399.752 ms |
3.1× faster than NumPy, 2.9× faster than EJML |
| Cholesky |
1.261 ms |
2.328 ms |
3.545 ms |
— |
1.8× faster than NumPy, 2.8× faster than EJML |
| QR Factorization |
46.170 ms |
12.622 ms |
7.447 ms |
586.330 ms |
12.7× faster than ND4J |
Size and deploy :- JNum is under 500kb and available of maven central just simple dependencies and you can use it
<dependency>
<groupId>io.github.ch-abhinav</groupId>
<artifactId>jnum</artifactId>
<version>0.2.0</version>
</dependency>
What I want from you guys is simple, Try using JNum and see how it works it gives me motivation to continue. If community helps me build the library then yes having performance on par to native libraries isn't that far.
If you guys can run on other Architectures and Operating Systems give feedback and try to contribute in project it will be great because I can't do that. Since project is has grown a lot without people helping it out it's very tough task for me :(
That's why I have 6 good-first issues worth trying for. It will be even more great if people make there own issues and enhancement proposals.
TO JDK devs:-
1. Vector API is amazing tool but when I do SIMD operations I expect less warmup time but that's not the case i my library.
2. when I stop a JMH benchmark midway it's causing Zombie runs (mainly with multithreaded programs) basically because of off heap memory calculations benchmarks sometimes don't stop and run even though terminal running that is closed. IDK if this is windows only bug or intended feature or random event but once check it out please. My 10k x 10k 5 matmuls which are multithreaded become zombie process basically take 100% of cpu throughput for basically a program which should have stopped long ago.