Skip to content

Commit 3c86495

Browse files
authored
custom native lib support (#66)
1 parent 6a9c97f commit 3c86495

File tree

2 files changed

+50
-23
lines changed

2 files changed

+50
-23
lines changed

README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,18 @@ For Debian Linux:
6262
apt install libgomp1
6363
```
6464

65+
### GPU support
66+
67+
It is possible to force GPU support for a training:
68+
* rebuild the [LightGBM with GPU support]: use `-DUSE_CUDA=1 -DUSE_SWIG=ON` CMake options. You should also match the native/JNI versions precisely.
69+
* LightGBM4j loads native libraries by default from bundled resources. This can be overridden by setting the `LIGHTGBM_NATIVE_LIB_PATH` environment variable. It should point to a directory with `lib_lightgbm.so` and `lib_lightgbm_swig.so` files (or with `dll`/`dylib` extensions on Windows/MacOS).
70+
71+
If the native override was able to successfully load a custom library you've built, then you'll see the following line in logs:
72+
```
73+
LIGHTGBM_NATIVE_LIB_PATH is set: loading /home/user/code/LightGBM/lib_lightgbm.so
74+
LIGHTGBM_NATIVE_LIB_PATH is set: loading /home/user/code/LightGBM/lib_lightgbm_swig.so
75+
```
76+
6577
## Usage
6678

6779
There are two main classes available:

src/main/java/io/github/metarank/lightgbm4j/LGBMBooster.java

Lines changed: 38 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,12 @@ public synchronized static void loadNative() throws IOException {
4949
if (os.startsWith("Linux") || os.startsWith("LINUX")) {
5050
try {
5151
if (arch.startsWith("amd64") || arch.startsWith("x86_64")) {
52-
loadNative("linux/x86_64/lib_lightgbm.so", "lib_lightgbm.so");
53-
loadNative("linux/x86_64/lib_lightgbm_swig.so", "lib_lightgbm_swig.so");
52+
loadNative("linux/x86_64/", "lib_lightgbm.so");
53+
loadNative("linux/x86_64/", "lib_lightgbm_swig.so");
5454
nativeLoaded = true;
5555
} else if (arch.startsWith("aarch64") || arch.startsWith("arm64")) {
56-
loadNative("linux/aarch64/lib_lightgbm.so", "lib_lightgbm.so");
57-
loadNative("linux/aarch64/lib_lightgbm_swig.so", "lib_lightgbm_swig.so");
56+
loadNative("linux/aarch64/", "lib_lightgbm.so");
57+
loadNative("linux/aarch64/", "lib_lightgbm_swig.so");
5858
nativeLoaded = true;
5959
}
6060
} catch (UnsatisfiedLinkError err) {
@@ -73,12 +73,12 @@ public synchronized static void loadNative() throws IOException {
7373
} else if (os.startsWith("Mac")) {
7474
try {
7575
if (arch.startsWith("amd64") || arch.startsWith("x86_64")) {
76-
loadNative("osx/x86_64/lib_lightgbm.dylib", "lib_lightgbm.dylib");
77-
loadNative("osx/x86_64/lib_lightgbm_swig.dylib", "lib_lightgbm_swig.dylib");
76+
loadNative("osx/x86_64/", "lib_lightgbm.dylib");
77+
loadNative("osx/x86_64/", "lib_lightgbm_swig.dylib");
7878
nativeLoaded = true;
7979
} else if (arch.startsWith("aarch64") || arch.startsWith("arm64")) {
80-
loadNative("osx/aarch64/lib_lightgbm.dylib", "lib_lightgbm.dylib");
81-
loadNative("osx/aarch64/lib_lightgbm_swig.dylib", "lib_lightgbm_swig.dylib");
80+
loadNative("osx/aarch64/", "lib_lightgbm.dylib");
81+
loadNative("osx/aarch64/", "lib_lightgbm_swig.dylib");
8282
nativeLoaded = true;
8383
} else {
8484
System.out.println("arch " + arch + " is not supported");
@@ -100,8 +100,8 @@ public synchronized static void loadNative() throws IOException {
100100
throw err;
101101
}
102102
} else if (os.startsWith("Windows")) {
103-
loadNative("windows/x86_64/lib_lightgbm.dll", "lib_lightgbm.dll");
104-
loadNative("windows/x86_64/lib_lightgbm_swig.dll", "lib_lightgbm_swig.dll");
103+
loadNative("windows/x86_64/", "lib_lightgbm.dll");
104+
loadNative("windows/x86_64/", "lib_lightgbm_swig.dll");
105105
nativeLoaded = true;
106106
} else {
107107
System.out.println("Only Linux@x86_64, Windows@x86_64, Mac@x86_64 and Mac@aarch are supported");
@@ -110,20 +110,35 @@ public synchronized static void loadNative() throws IOException {
110110
}
111111

112112
private static void loadNative(String path, String name) throws IOException, UnsatisfiedLinkError {
113-
System.out.println("Loading native lib " + path);
114-
String tmp = System.getProperty("java.io.tmpdir");
115-
File libFile = new File(tmp + File.separator + name);
116-
if (libFile.exists()) {
117-
System.out.println(libFile + " already exists");
113+
String nativePathOverride = System.getenv("LIGHTGBM_NATIVE_LIB_PATH");
114+
if (nativePathOverride != null) {
115+
if (!nativePathOverride.endsWith("/")) {
116+
nativePathOverride = nativePathOverride + "/";
117+
}
118+
String libFile = nativePathOverride + name;
119+
System.out.println("LIGHTGBM_NATIVE_LIB_PATH is set: loading " + libFile);
120+
try {
121+
System.load(libFile);
122+
} catch (UnsatisfiedLinkError err) {
123+
System.out.println("Cannot load library:" + err.getMessage());
124+
throw err;
125+
}
118126
} else {
119-
extractResource(path, name, libFile);
120-
}
121-
System.out.println("Extracted file: exists=" + libFile.exists() + " path=" + libFile);
122-
try {
123-
System.load(libFile.toString());
124-
} catch (UnsatisfiedLinkError err) {
125-
System.out.println("Cannot load library:" + err.getMessage());
126-
throw err;
127+
System.out.println("Loading native lib from resource " + path + "/" + name);
128+
String tmp = System.getProperty("java.io.tmpdir");
129+
File libFile = new File(tmp + File.separator + name);
130+
if (libFile.exists()) {
131+
System.out.println(libFile + " already exists");
132+
} else {
133+
extractResource(path + name, name, libFile);
134+
}
135+
System.out.println("Extracted file: exists=" + libFile.exists() + " path=" + libFile);
136+
try {
137+
System.load(libFile.toString());
138+
} catch (UnsatisfiedLinkError err) {
139+
System.out.println("Cannot load library:" + err.getMessage());
140+
throw err;
141+
}
127142
}
128143
}
129144

0 commit comments

Comments
 (0)