How do I use Intel® MKL with Java*?
Published:03/27/2013 Last Updated:03/27/2013
Intel® MKL C functions can be accessed from Java through Java Native Interface (JNI). The following example shows how to call cblas_dgemm from java on Linux. For more examples see the attachment located at the bottom of this article.
CAUTION: This article demonstrates usage model for arrays of size less than 2 billion and is aimed at proficient Java users capable of creating native arrays, verify input and do Java optimizations.
To call cblas_dgemm from java application following steps should be performed:
Step 1. Create a java file with cblas dgemm description (CBLAS.java):
/*CBLAS.java*/
public final class CBLAS {
private CBLAS() {}
static {
System.loadLibrary("mkl_java_stubs"); /*load library (which will contain wrapper for cblas function. See step 3)*/
}
public final static class ORDER {
private ORDER() {}
/** row-major arrays */
public final static int RowMajor=101;
/** column-major arrays */
public final static int ColMajor=102;
}
public final static class TRANSPOSE {
private TRANSPOSE() {}
/** trans='N' */
public final static int NoTrans =111;
/** trans='T' */
public final static int Trans=112;
/** trans='C' */
public final static int ConjTrans=113;
}
public static native void dgemm(int Order, int TransA, int TransB, int M, int N, int K, double alpha, double[] A, int lda, double[] B, int ldb, double beta, double[] C, int ldc); /*inform java virtual machine that function is defined externally*/
}
Compile the CBLAS.java using the java compiler as below:
javac CBLAS.java
Step 2. Generate headers files from the java class file which was created in the previous step.
These headers should be used in C file in the next step.
javah CBLAS
Three header files will be generated: CBLAS.h, CBLAS_ORDER.h CBLAS_TRANSPOSE.h
Step 3. Use definition of Java_CBLAS_dgemm in header CBLAS.h that was generated in step 2 to write C file CBLAS.c.
Here’s generated header CBLAS.h – do not edit it!
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class CBLAS */
#ifndef _Included_CBLAS
#define _Included_CBLAS
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: CBLAS
* Method: dgemm
* Signature: (IIIIIID[DI[DID[DI)V
*/
JNIEXPORT void JNICALL Java_CBLAS_dgemm
(JNIEnv *, jclass, jint, jint, jint, jint, jint, jint, jdouble, jdoubleArray, jint, jdoubleArray, jint, jdouble, jdoubleArray, jint);
#ifdef __cplusplus
}
#endif
#endif
Definition of function Java_CBLAS_dgemm should be used in wrapper for MKL. Create C file CBLAS.c:
/*CBLAS.c*/
#include <jni.h>
#include <assert.h>
#include "mkl_cblas.h"
JNIEXPORT void Java_CBLAS_dgemm (JNIEnv *env, jclass klass, jint Order, jint TransA, jint TransB, jint M, jint N, jint K, jdouble alpha, jdoubleArray A, int lda, jdoubleArray B, jint ldb, jdouble beta, jdoubleArray C, jint ldc){
jdouble *aElems, *bElems, *cElems;
aElems = (*env)-> GetDoubleArrayElements (env,A,NULL);
bElems = (*env)-> GetDoubleArrayElements (env,B,NULL);
cElems = (*env)-> GetDoubleArrayElements (env,C,NULL);
assert(aElems && bElems && cElems);
cblas_dgemm ((CBLAS_ORDER)Order,(CBLAS_TRANSPOSE)TransA,(CBLAS_TRANSPOSE)TransB,
(int)M,(int)N,(int)K,alpha,aElems,(int)lda,bElems,(int)ldb,beta,cElems,(int)ldc);
(*env)-> ReleaseDoubleArrayElements (env,C,cElems,0);
(*env)-> ReleaseDoubleArrayElements (env,B,bElems,JNI_ABORT);
(*env)-> ReleaseDoubleArrayElements (env,A,aElems,JNI_ABORT);
}
This file should be compiled to create native library libmkl_java_stubs.so (Loading of this library in java is described in step 1)
icc -shared -fPIC -o libmkl_java_stubs.so CBLAS.c -I. -I$MKLROOT/include -Wl,--start-group $MKLROOT/lib/intel64/libmkl_intel_lp64.a $MKLROOT/lib/intel64/libmkl_intel_thread.a $MKLROOT/lib/intel64/libmkl_core.a -Wl,--end-group -openmp -lpthread -lm -ldl
Step 4. Create main dgemm.java
/*dgemm.java*/
public final class dgemm {
/** Incarnation prohibited. */
private dgemm() {}
/** No command-line options. */
public static void main(String[] args) {
//
// Prepare the matrices and other parameters
//
int Order = CBLAS.ORDER.RowMajor;
int TransA = CBLAS.TRANSPOSE.NoTrans;
int TransB = CBLAS.TRANSPOSE.NoTrans;
int M=2, N=4, K=3;
int lda=K, ldb=N, ldc=N;
double[] A = new double[] {1,2,3, 4,5,6};
double[] B = new double[] {0,1,0,1, 1,0,0,1, 1,0,1,0};
double[] C = new double[] {5,1,3,3, 11,4,6,9};
double alpha=1, beta=-1;
//
// Print the parameters
//
System.out.println("alpha=" + string(alpha));
System.out.println("beta=" + string(beta));
printMatrix("Matrix A",A,M,K);
printMatrix("Matrix B",B,K,N);
printMatrix("Initial C",C,M,N);
//
// Compute the function
//
CBLAS.dgemm(Order,TransA,TransB,M,N,K,alpha,A,lda,B,ldb,beta,C,ldc);
//
// Print the result
//
printMatrix("Resulting C",C,M,N);
//
// Check the result:
//
boolean error=false;
for (int m=0; m<M; m++)
for (int n=0; n<N; n++)
if (C[m*N+n] != 0)
error=true;
if (error)
System.out.println("ERROR: resulting C must be zero!");
//
// Print summary and exit
//
if (error) {
System.out.println("TEST FAILED");
System.exit(1);
}
System.out.println("TEST PASSED");
}
/** Print the matrix X assuming raw-major order of elements. */
private static void printMatrix(String prompt, double[] X, int I, int J) {
System.out.println(prompt);
for (int i=0; i<I; i++) {
for (int j=0; j<J; j++)
System.out.print("\t" + string(X[i*J+j]));
System.out.println();
}
}
/** Shorter string for real number. */
private static String string(double re) {
String s="";
if (re == (long)re)
s += (long)re;
else
s += re;
return s;
}
}
Compile the application
javac dgemm.java
Step 5. Execute the application.
java.library.path should point to directory where library libmkl_java_stubs.so is placed. This example assumes that stubs shared library is located next to the created Java executable.
java -Djava.library.path=. dgemm
The output should be:
alpha=1
beta=-1
Matrix A
1 2 3
4 5 6
Matrix B
0 1 0 1
1 0 0 1
1 0 1 0
Initial C
5 1 3 3
11 4 6 9
Resulting C
0 0 0 0
0 0 0 0
TEST PASSED
The source code for the above dgemm mkl example is attached below.
Attachment | Size |
---|---|
dgemm-java-example.zip | 2.2 KB |
intel-mkl-java-examples.zip | 1.2 MB |
Product and Performance Information
Performance varies by use, configuration and other factors. Learn more at www.Intel.com/PerformanceIndex.