Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JNI concurrent interface extensions #1215

Merged
merged 8 commits into from
Apr 29, 2017
13 changes: 9 additions & 4 deletions java/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,22 @@ endif
VWLIBS := -L../vowpalwabbit -l vw
STDLIBS = $(BOOST_LIBRARY) $(LIBS)
JAVA_INCLUDE = -I $(JAVA_HOME)/include
LIB_NAME = "vw_jni"

ifeq ($(UNAME), Linux)
OS_DEPENDENT_LIB_TARGET = "lib$(LIB_NAME).so"
JAVA_INCLUDE += -I $(JAVA_HOME)/include/linux
endif
ifeq ($(UNAME), FreeBSD)
OS_DEPENDENT_LIB_TARGET = "lib$(LIB_NAME).so"
JAVA_INCLUDE += -I $(JAVA_HOME)/include/linux
endif
ifeq "CYGWIN" "$(findstring CYGWIN,$(UNAME))"
OS_DEPENDENT_LIB_TARGET = "$(LIB_NAME).dll"
JAVA_INCLUDE += -I $(JAVA_HOME)/include/linux
endif
ifeq ($(UNAME), Darwin)
OS_DEPENDENT_LIB_TARGET = "lib$(LIB_NAME).dylib"
JAVA_INCLUDE += -I $(JAVA_HOME)/include/darwin
endif

Expand All @@ -29,14 +34,14 @@ all:
test:
cd ..; $(MAKE) test

things: pom_version target/vw_jni.lib
things: pom_version target/$(OS_DEPENDENT_LIB_TARGET)

pom_version: pom.xml
ver=$$(grep AC_INIT ../configure.ac | cut -d '[' -f 3 | cut -d ']' -f 1) && \
newVer=$$(perl -e "@a=split('\.', '$$ver'); \$$a[2]++; print(join('.', @a))") && \
perl -pi -e "s/(\s*)<version>.*-SNAPSHOT/\1<version>$$newVer-SNAPSHOT/" pom.xml

target/vw_jni.lib: $(jni_OBJS) ../vowpalwabbit/main.o ../vowpalwabbit/libvw.a ../vowpalwabbit/liballreduce.a
target/$(OS_DEPENDENT_LIB_TARGET): $(jni_OBJS) ../vowpalwabbit/main.o ../vowpalwabbit/libvw.a ../vowpalwabbit/liballreduce.a
mkdir -p target;
$(CXX) -shared $(FLAGS) -o $@ $^ $(VWLIBS) $(STDLIBS) $(JAVA_INCLUDE)

Expand All @@ -50,5 +55,5 @@ target/vw_jni.lib: $(jni_OBJS) ../vowpalwabbit/main.o ../vowpalwabbit/libvw.a ..

.PHONY: clean
clean:
rm -f target/vw_jni.lib
rm -f $(jni_SRCS:.cc=.o)
rm -f target/$(OS_DEPENDANT_LIB_TARGET)
rm -f $(jni_OBJS)
14 changes: 11 additions & 3 deletions java/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

<groupId>com.github.johnlangford</groupId>
<artifactId>vw-jni</artifactId>
<version>8.2.2-SNAPSHOT</version>
<version>8.3.3-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Vowpal Wabbit JNI Layer</name>
<description>
Expand Down Expand Up @@ -71,11 +71,19 @@
<testResource>
<directory>${project.build.directory}</directory>
<includes>
<include>vw_jni.*lib</include>
<include>*vw_jni.*</include>
</includes>
</testResource>
</testResources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<forkMode>once</forkMode>
<argLine>-Djava.library.path=./target</argLine>
</configuration>
</plugin>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>2.6.1</version>
Expand Down Expand Up @@ -173,7 +181,7 @@
<resource>
<directory>${project.build.directory}</directory>
<includes>
<include>vw_jni.*lib</include>
<include>*vw_jni.*</include>
</includes>
</resource>
</resources>
Expand Down
12 changes: 12 additions & 0 deletions java/src/main/c++/vowpalWabbit_learner_VWLearners.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,18 @@ JNIEXPORT jlong JNICALL Java_vowpalWabbit_learner_VWLearners_initialize(JNIEnv *
return vwPtr;
}

JNIEXPORT jlong JNICALL Java_vowpalWabbit_learner_VWLearners_seedVWModel(JNIEnv *env, jclass obj, jlong vwPtr)
{ jlong cloneVwPtr = 0;
try
{ vw* vwInstance = VW::seed_vw_model((vw*)vwPtr, "");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does seed_vw_model do?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ref: https://github.com/JohnLangford/vowpal_wabbit/blob/462ed1624967d99a349527edd108a6f62ed92b9a/vowpalwabbit/parse_args.cc#L1400-L1424

It initializes new VW instances using the parameters from an existing instance (seed), these cloned VW instances shares the shared data with the the seed instance.

The seed_vw_model method is expected to make the concurrent methods more memory efficient.

cloneVwPtr = (jlong)vwInstance;
}
catch(...)
{ rethrow_cpp_exception_as_java_exception(env);
}
return cloneVwPtr;
}

JNIEXPORT void JNICALL Java_vowpalWabbit_learner_VWLearners_closeInstance(JNIEnv *env, jclass obj, jlong vwPtr)
{ try
{ VW::finish(*((vw*)vwPtr));
Expand Down
8 changes: 8 additions & 0 deletions java/src/main/c++/vowpalWabbit_learner_VWLearners.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

81 changes: 80 additions & 1 deletion java/src/main/c++/vowpalWabbit_learner_VWMulticlassLearner.cc
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
#include <string>
#include "vowpalWabbit_learner_VWMulticlassLearner.h"
#include "../../../../vowpalwabbit/vw.h"
#include "jni_base_learner.h"

jint multiclass_predictor(example* vec, JNIEnv *env) { return vec->pred.multiclass; }
jint multiclass_predictor(example* vec, JNIEnv *env){ return vec->pred.multiclass; }

JNIEXPORT jint JNICALL Java_vowpalWabbit_learner_VWMulticlassLearner_predict(JNIEnv *env, jobject obj, jstring example_string, jboolean learn, jlong vwPtr)
{ return base_predict<jint>(env, example_string, learn, vwPtr, multiclass_predictor);
Expand All @@ -11,3 +12,81 @@ JNIEXPORT jint JNICALL Java_vowpalWabbit_learner_VWMulticlassLearner_predict(JNI
JNIEXPORT jint JNICALL Java_vowpalWabbit_learner_VWMulticlassLearner_predictMultiline(JNIEnv *env, jobject obj, jobjectArray example_strings, jboolean learn, jlong vwPtr)
{ return base_predict<jint>(env, example_strings, learn, vwPtr, multiclass_predictor);
}

/*
* private multiline prediction utility
* predict and annotates for multiline example string arrays
* results will be stored as example ptrs in the example array passed in
*/
void _predict_for_multilines(JNIEnv *env, jobject obj, jobjectArray example_strings, jboolean learn, jlong vwPtr, example** ex_array)
{ vw* vwInstance = (vw*)vwPtr;
int example_count = env->GetArrayLength(example_strings);

// first pass to process all examples without giving final predictions
for (int i=0; i<example_count; i++) {
jstring example_string = (jstring) (env->GetObjectArrayElement(example_strings, i));
example* ex = read_example(env, example_string, vwInstance);
base_predict<jint>(env, ex, learn, vwInstance, multiclass_predictor, false);
ex_array[i] = ex;
}

// release JVM references to examples
env->DeleteLocalRef(example_strings);

// close out examples
example* ex = read_example("\0", vwInstance);
base_predict<jint>(env, ex, learn, vwInstance, multiclass_predictor, false);

return;
}

JNIEXPORT jintArray JNICALL Java_vowpalWabbit_learner_VWMulticlassLearner_predictForAllLines(JNIEnv *env, jobject obj, jobjectArray example_strings, jboolean learn, jlong vwPtr)
{ int example_count = env->GetArrayLength(example_strings);
example** ex_array = new example*[example_count];

// annotate examples for inputs
_predict_for_multilines(env, obj, example_strings, learn, vwPtr, ex_array);

// second pass to collect all predictions in int
jint* pred_c_array = new jint[example_count];
for (int i=0; i<example_count; i++) {
pred_c_array[i] = ex_array[i]->pred.multiclass;
}

// alloc pred_j_array
jintArray pred_j_array = env->NewIntArray(example_count);
env->SetIntArrayRegion(pred_j_array, 0, example_count, pred_c_array);

// release allocated resources
delete[] pred_c_array;
delete[] ex_array;
return pred_j_array;
}

JNIEXPORT jobjectArray JNICALL Java_vowpalWabbit_learner_VWMulticlassLearner_predictNamedLabelsForAllLines(JNIEnv *env, jobject obj, jobjectArray example_strings, jboolean learn, jlong vwPtr)
{ vw* vwInstance = (vw*)vwPtr;
int example_count = env->GetArrayLength(example_strings);
example** ex_array = new example*[example_count];

// annotate examples for inputs
_predict_for_multilines(env, obj, example_strings, learn, vwPtr, ex_array);

// second pass to collect all pretty string predictions from annotated examples
jobjectArray pred_j_str_array = env->NewObjectArray(example_count, env->FindClass("java/lang/String"), NULL);
for (int i=0; i<example_count; i++) {
jstring pretty_pred_str = NULL;
if (vwInstance->sd->ldict) {
// if name labels were provided, use the named labels from model
substring ss = vwInstance->sd->ldict->get(ex_array[i]->pred.multiclass);
pretty_pred_str = env->NewStringUTF(std::string(ss.begin, ss.end-ss.begin).c_str());
} else {
// else use the string value of the multiclass prediction index as an output
pretty_pred_str = env->NewStringUTF(std::to_string(ex_array[i]->pred.multiclass).c_str());
}
env->SetObjectArrayElement(pred_j_str_array, i, pretty_pred_str);
}

// release allocated resources
delete[] ex_array;
return pred_j_str_array;
}
22 changes: 19 additions & 3 deletions java/src/main/c++/vowpalWabbit_learner_VWMulticlassLearner.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading