diff --git a/mindspore/lite/build_lite.sh b/mindspore/lite/build_lite.sh index b0a1b04874..cf8eed8331 100755 --- a/mindspore/lite/build_lite.sh +++ b/mindspore/lite/build_lite.sh @@ -110,7 +110,16 @@ build_lite_x86_64_jni_and_jar() { # build jar ${LITE_JAVA_PATH}/java/gradlew clean -p ${LITE_JAVA_PATH}/ - ${LITE_JAVA_PATH}/java/gradlew releaseJar -p ${LITE_JAVA_PATH}/ + if [[ "${ENABLE_ASAN}" == "ON" || "${ENABLE_ASAN}" == "on" ]] ; then + ${LITE_JAVA_PATH}/java/gradlew releaseJar -p ${LITE_JAVA_PATH}/ -x test + else + if [[ "${MSLITE_ENABLE_TESTCASES}" == "ON" || "${MSLITE_ENABLE_TESTCASES}" == "on" ]] ; then + export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${LITE_JAVA_PATH}/native/libs/linux_x86/ + ${LITE_JAVA_PATH}/java/gradlew releaseJar -p ${LITE_JAVA_PATH}/ + else + ${LITE_JAVA_PATH}/java/gradlew releaseJar -p ${LITE_JAVA_PATH}/ -x test + fi + fi cp ${LITE_JAVA_PATH}/build/lib/jar/*.jar ${BASEPATH}/output/tmp/${pkg_name}/runtime/lib/ # package @@ -415,7 +424,7 @@ build_aar() { ${LITE_JAVA_PATH}/java/gradlew build -p ${LITE_JAVA_PATH}/java/common # build new java api module ${LITE_JAVA_PATH}/java/gradlew clean -p ${LITE_JAVA_PATH}/ - ${LITE_JAVA_PATH}/java/gradlew build -p ${LITE_JAVA_PATH}/ + ${LITE_JAVA_PATH}/java/gradlew build -p ${LITE_JAVA_PATH}/ -x test # build aar local npu_bak=${MSLITE_ENABLE_NPU} diff --git a/mindspore/lite/java/build.gradle b/mindspore/lite/java/build.gradle index cc6b824dd6..f8ec3305c6 100644 --- a/mindspore/lite/java/build.gradle +++ b/mindspore/lite/java/build.gradle @@ -21,12 +21,19 @@ allprojects { apply plugin: 'java' dependencies { + testImplementation 'junit:junit:4.13' + implementation fileTree(dir: "libs", include: ["*.jar"]) implementation project(':linux_x86') } archivesBaseName = 'mindspore-lite-java' +test { + dependsOn 'cleanTest' + useJUnit() +} + task releaseJar(type: Jar) { from('java/common/build/classes/java/main') from('java/linux_x86/build/classes/java/main') diff --git a/mindspore/lite/java/native/CMakeLists.txt b/mindspore/lite/java/native/CMakeLists.txt index eeffbdc57a..4d908c1493 100644 --- a/mindspore/lite/java/native/CMakeLists.txt +++ b/mindspore/lite/java/native/CMakeLists.txt @@ -74,7 +74,6 @@ set(JNI_SRC ${NEW_NATIVE_DIR}/model.cpp ${NEW_NATIVE_DIR}/ms_context.cpp ${NEW_NATIVE_DIR}/ms_tensor.cpp - ${NEW_NATIVE_DIR}/train_config.cpp ${NEW_NATIVE_DIR}/version.cpp ) @@ -91,7 +90,10 @@ endif() if(SUPPORT_TRAIN) set(LITE_TRAIN_SO_NAME mindspore-lite-train minddata-lite) - set(JNI_TRAIN_SRC ${CMAKE_CURRENT_SOURCE_DIR}/runtime/train_session.cpp) + set(JNI_TRAIN_SRC + ${CMAKE_CURRENT_SOURCE_DIR}/runtime/train_session.cpp + ${NEW_NATIVE_DIR}/train_config.cpp + ) add_library(mindspore-lite-train-jni SHARED ${JNI_TRAIN_SRC}) if(PLATFORM_ARM64 OR PLATFORM_ARM32) find_library(log-lib log) diff --git a/mindspore/lite/java/src/main/java/com/mindspore/Graph.java b/mindspore/lite/java/src/main/java/com/mindspore/Graph.java index 7945879204..f9395f9549 100644 --- a/mindspore/lite/java/src/main/java/com/mindspore/Graph.java +++ b/mindspore/lite/java/src/main/java/com/mindspore/Graph.java @@ -36,8 +36,8 @@ public class Graph { * @param file model file. * @return load status. */ - public boolean Load(String file) { - this.graphPtr = load(file); + public boolean load(String file) { + this.graphPtr = loadModel(file); return this.graphPtr != 0L; } @@ -58,7 +58,7 @@ public class Graph { graphPtr = 0; } - private native long load(String file); + private native long loadModel(String file); private native boolean free(long graphPtr); } \ No newline at end of file diff --git a/mindspore/lite/java/src/main/java/com/mindspore/MSTensor.java b/mindspore/lite/java/src/main/java/com/mindspore/MSTensor.java index 92d446cdc9..2ef6e6c065 100644 --- a/mindspore/lite/java/src/main/java/com/mindspore/MSTensor.java +++ b/mindspore/lite/java/src/main/java/com/mindspore/MSTensor.java @@ -17,11 +17,13 @@ package com.mindspore; import java.nio.ByteBuffer; +import java.util.List; public class MSTensor { static { System.loadLibrary("mindspore-lite-jni"); } + private long tensorPtr; /** @@ -46,8 +48,9 @@ public class MSTensor { * @param tensorName tensor name * @param buffer tensor buffer */ - public MSTensor(String tensorName, ByteBuffer buffer) { - this.tensorPtr = createTensor(tensorName, buffer); + public static MSTensor createTensor(String tensorName, int dataType, int[] tensorShape, ByteBuffer buffer) { + long tensorPtr = createTensorByNative(tensorName, dataType, tensorShape, buffer); + return new MSTensor(tensorPtr); } /** @@ -111,6 +114,9 @@ public class MSTensor { * @return whether set data success. */ public boolean setData(byte[] data) { + if (data == null) { + return false; + } return this.setData(this.tensorPtr, data, data.length); } @@ -164,7 +170,8 @@ public class MSTensor { return tensorPtr; } - private native long createTensor(String tensorName, ByteBuffer buffer); + private static native long createTensorByNative(String tensorName, int dataType, int[] tesorShape, + ByteBuffer buffer); private native int[] getShape(long tensorPtr); diff --git a/mindspore/lite/java/src/main/java/com/mindspore/Model.java b/mindspore/lite/java/src/main/java/com/mindspore/Model.java index 99c8c199c3..b219c51f11 100644 --- a/mindspore/lite/java/src/main/java/com/mindspore/Model.java +++ b/mindspore/lite/java/src/main/java/com/mindspore/Model.java @@ -47,6 +47,9 @@ public class Model { * @return build status. */ public boolean build(Graph graph, MSContext context, TrainCfg cfg) { + if (graph == null || context == null || cfg == null) { + return false; + } modelPtr = this.buildByGraph(graph.getGraphPtr(), context.getMSContextPtr(), cfg.getTrainCfgPtr()); return modelPtr != 0; } @@ -63,6 +66,9 @@ public class Model { */ public boolean build(final MappedByteBuffer buffer, int modelType, MSContext context, char[] dec_key, String dec_mode) { + if (context == null) { + return false; + } modelPtr = this.buildByBuffer(buffer, modelType, context.getMSContextPtr(), dec_key, dec_mode); return modelPtr != 0; } @@ -76,6 +82,9 @@ public class Model { * @return model build status. */ public boolean build(final MappedByteBuffer buffer, int modelType, MSContext context) { + if (context == null) { + return false; + } modelPtr = this.buildByBuffer(buffer, modelType, context.getMSContextPtr(), null, ""); return modelPtr != 0; } @@ -92,6 +101,9 @@ public class Model { * @return model build status. */ public boolean build(String modelPath, int modelType, MSContext context, char[] dec_key, String dec_mode) { + if (context == null) { + return false; + } modelPtr = this.buildByPath(modelPath, modelType, context.getMSContextPtr(), dec_key, dec_mode); return modelPtr != 0; } @@ -105,6 +117,9 @@ public class Model { * @return build status. */ public boolean build(String modelPath, int modelType, MSContext context) { + if (context == null) { + return false; + } modelPtr = this.buildByPath(modelPath, modelType, context.getMSContextPtr(), null, ""); return modelPtr != 0; } @@ -135,6 +150,9 @@ public class Model { * @return Whether the resize is successful. */ public boolean resize(List inputs, int[][] dims) { + if (inputs == null || dims == null) { + return false; + } long[] inputsArray = new long[inputs.size()]; for (int i = 0; i < inputs.size(); i++) { inputsArray[i] = inputs.get(i).getMSTensorPtr(); @@ -230,6 +248,9 @@ public class Model { * @return Whether the model features is successfully update. */ public boolean updateFeatureMaps(List features) { + if (features == null) { + return false; + } long[] inputsArray = new long[features.size()]; for (int i = 0; i < features.size(); i++) { inputsArray[i] = features.get(i).getMSTensorPtr(); @@ -294,4 +315,4 @@ public class Model { private native List getFeatureMaps(long modelPtr); private native boolean updateFeatureMaps(long modelPtr, long[] newFeatures); -} \ No newline at end of file +} diff --git a/mindspore/lite/java/src/main/native/graph.cpp b/mindspore/lite/java/src/main/native/graph.cpp index 9ef691b848..7c7b85c09a 100644 --- a/mindspore/lite/java/src/main/native/graph.cpp +++ b/mindspore/lite/java/src/main/native/graph.cpp @@ -20,7 +20,7 @@ #include "include/api/serialization.h" #include "include/api/types.h" -extern "C" JNIEXPORT jlong JNICALL Java_com_mindspore_Graph_load(JNIEnv *env, jobject thiz, jstring ms_file) { +extern "C" JNIEXPORT jlong JNICALL Java_com_mindspore_Graph_loadModel(JNIEnv *env, jobject thiz, jstring ms_file) { auto graph = new (std::nothrow) mindspore::Graph(); if (graph == nullptr) { MS_LOGE("Model new failed"); @@ -35,3 +35,13 @@ extern "C" JNIEXPORT jlong JNICALL Java_com_mindspore_Graph_load(JNIEnv *env, jo } return jlong(graph); } + +extern "C" JNIEXPORT void JNICALL Java_com_mindspore_Graph_free(JNIEnv *env, jobject thiz, jlong graph_ptr) { + auto *pointer = reinterpret_cast(graph_ptr); + if (pointer == nullptr) { + MS_LOGE("Model pointer from java is nullptr"); + return; + } + auto *lite_graph_ptr = static_cast(pointer); + delete (lite_graph_ptr); +} diff --git a/mindspore/lite/java/src/main/native/model.cpp b/mindspore/lite/java/src/main/native/model.cpp index e827c257fb..ef1cdc9e63 100644 --- a/mindspore/lite/java/src/main/native/model.cpp +++ b/mindspore/lite/java/src/main/native/model.cpp @@ -46,7 +46,6 @@ extern "C" JNIEXPORT jlong JNICALL Java_com_mindspore_Model_buildByGraph(JNIEnv return jlong(nullptr); } cfg.reset(c_cfg_ptr); - auto model = new (std::nothrow) mindspore::Model(); if (model == nullptr) { MS_LOGE("Model new failed"); @@ -225,6 +224,9 @@ jlong GetTensorByInOutName(JNIEnv *env, jlong model_ptr, jstring tensor_name, bo } else { tensor = lite_model_ptr->GetOutputByTensorName(env->GetStringUTFChars(tensor_name, JNI_FALSE)); } + if (tensor.impl() == nullptr) { + return jlong(nullptr); + } auto tensor_ptr = std::make_unique(tensor); if (tensor_ptr == nullptr) { MS_LOGE("Make ms tensor failed"); diff --git a/mindspore/lite/java/src/main/native/ms_tensor.cpp b/mindspore/lite/java/src/main/native/ms_tensor.cpp index 56c166093b..9c16fe4fa1 100644 --- a/mindspore/lite/java/src/main/native/ms_tensor.cpp +++ b/mindspore/lite/java/src/main/native/ms_tensor.cpp @@ -258,20 +258,28 @@ extern "C" JNIEXPORT jstring JNICALL Java_com_mindspore_MSTensor_tensorName(JNIE return env->NewStringUTF(ms_tensor_ptr->Name().c_str()); } -extern "C" JNIEXPORT jlong JNICALL Java_com_mindspore_MSTensor_createTensor(JNIEnv *env, jobject thiz, - jstring tensor_name, jobject buffer) { - auto *p_data = reinterpret_cast(env->GetDirectBufferAddress(buffer)); // get buffer pointer - jlong data_len = env->GetDirectBufferCapacity(buffer); // get buffer capacity +extern "C" JNIEXPORT jlong JNICALL Java_com_mindspore_MSTensor_createTensorByNative(JNIEnv *env, jobject thiz, + jstring tensor_name, jint data_type, + jintArray tensor_shape, + jobject buffer) { + auto *p_data = reinterpret_cast(env->GetDirectBufferAddress(buffer)); + jlong data_len = env->GetDirectBufferCapacity(buffer); if (p_data == nullptr) { MS_LOGE("GetDirectBufferAddress return null"); return false; } - char *tensor_data(new char[data_len]); + char *tensor_data = new char[data_len]; memcpy(tensor_data, p_data, data_len); - int tensor_size = static_cast(data_len / sizeof(float)); - std::vector shape = {tensor_size}; + + auto size = static_cast(env->GetArrayLength(tensor_shape)); + std::vector c_shape(size); + jint *shape_pointer = env->GetIntArrayElements(tensor_shape, nullptr); + for (int i = 0; i < size; i++) { + c_shape[i] = static_cast(shape_pointer[i]); + } + env->ReleaseIntArrayElements(tensor_shape, shape_pointer, JNI_ABORT); auto tensor = mindspore::MSTensor::CreateTensor(env->GetStringUTFChars(tensor_name, JNI_FALSE), - mindspore::DataType::kNumberTypeFloat32, shape, tensor_data, data_len); + static_cast(data_type), c_shape, tensor_data, data_len); return jlong(tensor); } diff --git a/mindspore/lite/java/src/test/java/com/mindspore/GraphTest.java b/mindspore/lite/java/src/test/java/com/mindspore/GraphTest.java new file mode 100644 index 0000000000..872afe5650 --- /dev/null +++ b/mindspore/lite/java/src/test/java/com/mindspore/GraphTest.java @@ -0,0 +1,27 @@ +package com.mindspore; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +@RunWith(JUnit4.class) +public class GraphTest { + + @Test + public void testLoadFailed() { + Graph g = new Graph(); + assertFalse(g.load("./1.ms")); + } + + @Test + public void testLoadSuccess() { + Graph g = new Graph(); + String pro = System.getProperty("user.dir"); + System.out.println("output:"+pro); + assertTrue(g.load("../test/ut/src/runtime/kernel/arm/test_data/nets/lenet_train.ms")); + g.free(); + } +} diff --git a/mindspore/lite/java/src/test/java/com/mindspore/ModelTest.java b/mindspore/lite/java/src/test/java/com/mindspore/ModelTest.java new file mode 100644 index 0000000000..aaa9b7df16 --- /dev/null +++ b/mindspore/lite/java/src/test/java/com/mindspore/ModelTest.java @@ -0,0 +1,201 @@ +package com.mindspore; + +import com.mindspore.config.DataType; +import com.mindspore.config.DeviceType; +import com.mindspore.config.MSContext; +import com.mindspore.config.TrainCfg; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +import java.io.IOException; +import java.io.RandomAccessFile; +import java.nio.ByteBuffer; +import java.nio.FloatBuffer; +import java.nio.MappedByteBuffer; +import java.nio.channels.FileChannel; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +@RunWith(JUnit4.class) +public class ModelTest { + + @Test + public void testBuildByGraphSuccess() { + Graph g = new Graph(); + assertTrue(g.load("../test/ut/src/runtime/kernel/arm/test_data/nets/lenet_train.ms")); + MSContext context = new MSContext(); + context.init(1, 0); + context.addDeviceInfo(DeviceType.DT_CPU, false, 0); + TrainCfg cfg = new TrainCfg(); + cfg.init(); + Model liteModel = new Model(); + boolean isSuccess = liteModel.build(g, context, cfg); + assertTrue(isSuccess); + liteModel.free(); + } + + @Test + public void testBuildByGraphFailed() { + Graph g = new Graph(); + assertTrue(g.load("../test/ut/src/runtime/kernel/arm/test_data/nets/lenet_train.ms")); + MSContext context = new MSContext(); + TrainCfg cfg = new TrainCfg(); + Model liteModel = new Model(); + boolean isSuccess = liteModel.build(g, context, cfg); + assertFalse(isSuccess); + liteModel.free(); + } + + @Test + public void testBuildByFileSuccess() { + String modelFile = "../test/ut/src/runtime/kernel/arm/test_data/nets/lenet_tod_infer.ms"; + MSContext context = new MSContext(); + context.init(1, 0); + context.addDeviceInfo(DeviceType.DT_CPU, false, 0); + Model liteModel = new Model(); + boolean isSuccess = liteModel.build(modelFile, 0, context); + assertTrue(isSuccess); + liteModel.free(); + } + + @Test + public void testBuildByBufferSuccess() { + String fileName = "../test/ut/src/runtime/kernel/arm/test_data/nets/lenet_tod_infer.ms"; + FileChannel fc = null; + MappedByteBuffer byteBuffer = null; + try { + fc = new RandomAccessFile(fileName, "r").getChannel(); + byteBuffer = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size()).load(); + } catch (IOException e) { + e.printStackTrace(); + } + assertNotNull(byteBuffer); + MSContext context = new MSContext(); + context.init(1, 0); + context.addDeviceInfo(DeviceType.DT_CPU, false, 0); + Model liteModel = new Model(); + boolean isSuccess = liteModel.build(byteBuffer, 0, context); + assertTrue(isSuccess); + liteModel.free(); + } + + @Test + public void testBuildByFileFailed() { + String modelFile = "../test/ut/src/runtime/kernel/arm/test_data/nets/lenet_tod_infer.ms"; + MSContext context = new MSContext(); + Model liteModel = new Model(); + boolean isSuccess = liteModel.build(modelFile, 0, context); + assertFalse(isSuccess); + liteModel.free(); + } + + @Test + public void testPredictFailed() { + String modelFile = "../test/ut/src/runtime/kernel/arm/test_data/nets/lenet_tod_infer.ms"; + MSContext context = new MSContext(); + context.init(1, 0); + context.addDeviceInfo(DeviceType.DT_CPU, false, 0); + Model liteModel = new Model(); + boolean isSuccess = liteModel.build(modelFile, 0, context); + assertTrue(isSuccess); + isSuccess = liteModel.predict(); + assertFalse(isSuccess); + liteModel.free(); + } + + @Test + public void testPredictSuccess() { + String modelFile = "../test/ut/src/runtime/kernel/arm/test_data/nets/lenet_tod_infer.ms"; + MSContext context = new MSContext(); + context.init(1, 0); + context.addDeviceInfo(DeviceType.DT_CPU, false, 0); + Model liteModel = new Model(); + boolean isSuccess = liteModel.build(modelFile, 0, context); + assertTrue(isSuccess); + List msTensorList = liteModel.getInputs(); + assertEquals(1, msTensorList.size()); + for (MSTensor msTensor : msTensorList) { + byte[] temp = new byte[msTensor.elementsNum()]; + msTensor.setData(temp); + } + isSuccess = liteModel.predict(); + assertFalse(isSuccess); + List outputs = liteModel.getOutputs(); + for (MSTensor output : outputs) { + System.out.println("output-------" + output.tensorName()); + } + System.out.println(""); + MSTensor output = liteModel.getOutputByTensorName("Default/network-WithLossCell/_backbone-LeNet5/fc3-Dense" + + "/BiasAdd-op121"); + assertEquals(80, output.size()); + output = liteModel.getOutputByTensorName("Default/network-WithLossCell/_loss_fn-L1Loss/ReduceMean-op112"); + assertEquals(0, output.size()); + List inputs = liteModel.getInputs(); + for (MSTensor input : inputs) { + System.out.println(input.tensorName()); + } + liteModel.free(); + } + + @Test + public void testResize() { + String modelFile = "../test/ut/src/runtime/kernel/arm/test_data/nets/lenet_tod_infer.ms"; + MSContext context = new MSContext(); + context.init(1, 0); + context.addDeviceInfo(DeviceType.DT_CPU, false, 0); + Model liteModel = new Model(); + boolean isSuccess = liteModel.build(modelFile, 0, context); + List inputs = liteModel.getInputs(); + int[][] newShape = {{2, 32, 32, 1}}; + System.out.println(); + isSuccess = liteModel.resize(inputs, newShape); + assertTrue(isSuccess); + newShape[0][3] = 3; + isSuccess = liteModel.resize(inputs, newShape); + assertFalse(isSuccess); + liteModel.free(); + } + + @Test + public void testFeatureMap() { + String modelFile = "../test/ut/src/runtime/kernel/arm/test_data/nets/lenet_train.ms"; + Graph g = new Graph(); + assertTrue(g.load(modelFile)); + MSContext context = new MSContext(); + context.init(1, 0); + context.addDeviceInfo(DeviceType.DT_CPU, false, 0); + TrainCfg cfg = new TrainCfg(); + cfg.init(); + Model liteModel = new Model(); + boolean isSuccess = liteModel.build(g, context, cfg); + assertTrue(isSuccess); + int[] tensorShape = {6, 5, 5, 1}; + float[] tensorData = new float[6 * 5 * 5]; + Arrays.fill(tensorData, 0); + ByteBuffer byteBuf = ByteBuffer.allocateDirect(6 * 5 * 5 * 4); + FloatBuffer floatBuf = byteBuf.asFloatBuffer(); + floatBuf.put(tensorData); + MSTensor newTensor = MSTensor.createTensor("conv1.weight", DataType.kNumberTypeFloat32, tensorShape, byteBuf); + List msTensors = new ArrayList<>(); + msTensors.add(newTensor); + isSuccess = liteModel.updateFeatureMaps(msTensors); + assertTrue(isSuccess); + List weights = liteModel.getFeatureMaps(); + for (MSTensor weight : weights) { + if (weight.tensorName().equals("conv1.weight")) { + float[] weightData = weight.getFloatData(); + assertEquals(0L, weightData[0], 0.0); + break; + } + } + newTensor.free(); + liteModel.free(); + } +} diff --git a/mindspore/lite/test/ut/src/runtime/kernel/arm/test_data/nets/lenet_tod_infer.ms b/mindspore/lite/test/ut/src/runtime/kernel/arm/test_data/nets/lenet_tod_infer.ms new file mode 100644 index 0000000000..5fa71c3a7a Binary files /dev/null and b/mindspore/lite/test/ut/src/runtime/kernel/arm/test_data/nets/lenet_tod_infer.ms differ