Skip to content

Commit

Permalink
Make benchmark a standalone module (#1043)
Browse files Browse the repository at this point in the history
Change-Id: I3b169b2c27239ae57be09ca63cb24e032d32e4f6
  • Loading branch information
frankfliu authored Jun 21, 2021
1 parent 50e4c43 commit 5f85fcc
Show file tree
Hide file tree
Showing 14 changed files with 324 additions and 234 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ configure(javaProjects()) {
doFirst {
systemProperties System.getProperties()
systemProperties.remove("user.dir")
systemProperty "ai.djl.logging.level", "debug"
// systemProperty "ai.djl.logging.level", "debug"
systemProperty "org.slf4j.simpleLogger.defaultLogLevel", "debug"
systemProperty "org.slf4j.simpleLogger.log.org.mortbay.log", "warn"
systemProperty "disableProgressBar", "true"
Expand Down
57 changes: 1 addition & 56 deletions examples/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,6 @@ dependencies {
runtimeOnly "ai.djl.mxnet:mxnet-native-auto:${mxnet_version}"
}

// DLR, tflite, PaddlePaddle and OnnxRuntime are only used for benchmark
if (System.getProperty("ai.djl.default_engine") == "DLR") {
runtimeOnly project(":dlr:dlr-engine")
runtimeOnly "ai.djl.dlr:dlr-native-auto:${dlr_version}"
} else if (System.getProperty("ai.djl.default_engine") == "TFLite") {
runtimeOnly project(":tflite:tflite-engine")
runtimeOnly "ai.djl.tflite:tflite:tflite-native:${tflite_version}"
} else if (System.getProperty("ai.djl.default_engine") == "PaddlePaddle") {
runtimeOnly project(":paddlepaddle:paddlepaddle-model-zoo")
runtimeOnly "ai.djl.paddlepaddle:paddlepaddle-native-auto:${paddlepaddle_version}"
} else if (System.getProperty("ai.djl.default_engine") == "OnnxRuntime") {
// onnxruntime requires user install libgomp.so.1 manually, exclude from default dependency
runtimeOnly project(":onnxruntime:onnxruntime-engine")
}

testImplementation("org.testng:testng:${testng_version}") {
exclude group: "junit", module: "junit"
}
Expand All @@ -61,45 +46,5 @@ task listmodels(type: JavaExec) {
classpath = sourceSets.main.runtimeClasspath
main = "ai.djl.examples.inference.ListModels"
}

task benchmark(type: JavaExec) {
environment("TF_CPP_MIN_LOG_LEVEL", "1") // turn off TensorFlow print out
List<String> arguments = gradle.startParameter["taskRequests"]["args"].getAt(0)
for (String argument : arguments) {
if (argument.trim().startsWith("--args")) {
String[] line = argument.split("=", 2)
if (line.length == 2) {
line = line[1].split(" ");
if (line.contains("-t")) {
if (System.properties["ai.djl.default_engine"] == "PyTorch") {
System.setProperty("ai.djl.pytorch.num_interop_threads", "1")
System.setProperty("ai.djl.pytorch.num_threads", "1")
} else if (System.properties["ai.djl.default_engine"] == "TensorFlow") {
environment("OMP_NUM_THREADS", "1")
environment("TF_NUM_INTRAOP_THREADS", "1")
} else {
environment("MXNET_ENGINE_TYPE", "NaiveEngine")
environment("OMP_NUM_THREADS", "1")
}
}
break;
}
}
}

systemProperties System.getProperties()
systemProperties.remove("user.dir")
systemProperty("file.encoding", "UTF-8")
classpath = sourceSets.main.runtimeClasspath
// restrict the jvm heap size for better monitoring benchmark
jvmArgs = ["-Xmx2g"]
if (Boolean.getBoolean("loggc")) {
if (JavaVersion.current() == JavaVersion.VERSION_1_8) {
jvmArgs += ["-XX:+PrintGCTimeStamps", "-Xloggc:build/gc.log"]
} else {
jvmArgs += ["-Xlog:gc*=debug:file=build/gc.log"]
}
}
main = "ai.djl.examples.inference.benchmark.Benchmark"
}
tasks.distTar.enabled = false
tasks.distZip.enabled = false
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Benchmark your DL model

DJL offers a comprehensive script to benchmark the model on all different
DJL offers a comprehensive script to benchmark the model on all different
platforms for single-thread/multi-thread inference performance.This document will guide you how to run benchmark with DJL.

## Prerequisite
Expand Down Expand Up @@ -31,13 +31,13 @@ the 4-step instructions for your own model.
Benchmark on a Tensorflow model from http url with all-ones NDArray input for 10 times:

```
./gradlew benchmark -Dai.djl.default_engine=TensorFlow -Dai.djl.repository.zoo.location=https://storage.googleapis.com/tfhub-modules/tensorflow/resnet_50/classification/1.tar.gz --args='-c 10 -s 1,224,224,3'
./gradlew benchmark --args='-e TensorFlow -u https://storage.googleapis.com/tfhub-modules/tensorflow/resnet_50/classification/1.tar.gz -c 10 -s 1,224,224,3'
```

Similarly, this is for PyTorch

```
./gradlew benchmark -Dai.djl.default_engine=PyTorch -Dai.djl.repository.zoo.location=https://alpha-djl-demos.s3.amazonaws.com/model/djl-blockrunner/pytorch_resnet18.zip --args='-n traced_resnet18 -c 10 -s 1,3,224,224'
./gradlew benchmark --args='-e PyTorch -u https://alpha-djl-demos.s3.amazonaws.com/model/djl-blockrunner/pytorch_resnet18.zip -n traced_resnet18 -c 10 -s 1,3,224,224'
```

### Benchmark from ModelZoo
Expand All @@ -47,15 +47,15 @@ Similarly, this is for PyTorch
Resnet50 image classification model:

```
./gradlew benchmark --args="-c 1 -s 1,3,224,224 -a ai.djl.mxnet:resnet -r {'layers':'50','flavor':'v2','dataset':'imagenet'}"
./gradlew benchmark --args="-c 2 -s 1,3,224,224 -a ai.djl.mxnet:resnet -r {'layers':'50','flavor':'v2','dataset':'imagenet'}"
```

#### PyTorch

SSD object detection model:

```
./gradlew benchmark -Dai.djl.default_engine=PyTorch --args="-c 1 -s 1,3,300,300 -a ai.djl.pytorch:ssd -r {'size':'300','backbone':'resnet50'}"
./gradlew benchmark --args="-e PyTorch -c 2 -s 1,3,300,300 -a ai.djl.pytorch:ssd -r {'size':'300','backbone':'resnet50'}"
```


Expand All @@ -69,7 +69,7 @@ To start your benchmarking, we need to make sure we provide the following inform
- Sample input for the model
- (Optional) Multi-thread benchmark

The benchmark script located [here](https://github.com/deepjavalibrary/djl/blob/master/examples/src/main/java/ai/djl/examples/inference/benchmark/Benchmark.java).
The benchmark script located [here](https://github.com/deepjavalibrary/djl/blob/master/benchmark/src/main/java/ai/djl/benchmark/Benchmark.java).

Just do the following:

Expand All @@ -90,42 +90,52 @@ usage: ./gradlew benchmark --args='[OPTIONS]'
-a,--artifact-id <ARTIFACT-ID> Model artifact id.
-c,--iteration <ITERATION> Number of total iterations (per thread).
-d,--duration <DURATION> Duration of the test in minutes.
-e,--engine-name <ENGINE-NAME> Engine name.
-e,--engine <ENGINE-NAME> Choose an Engine for the benchmark.
-h,--help Print this help.
-l,--delay <DELAY> Delay of incremental threads.
-n,--model-name <MODEL-NAME> Model name.
-n,--model-name <MODEL-NAME> Specify model file name.
-o,--output-dir <OUTPUT-DIR> Directory for output logs.
-p,--model-path <MODEL-PATH> Model directory file path.
-r,--criteria <CRITERIA> The criteria (json string) used for searching the model.
-s,--input-shapes <INPUT-SHAPES> Input data shapes for non-CV model.
-s,--input-shapes <INPUT-SHAPES> Input data shapes for the model.
-t,--threads <NUMBER_THREADS> Number of inference threads.
-u,--model-url <MODEL-URL> Model archive file URL.
```

### Step 1: Pick your deep engine

By default, the above script will use MXNet as the default Engine, but you can always change that by adding the followings:

```
-Dai.djl.default_engine=TensorFlow # tensorflow
-Dai.djl.default_engine=PyTorch # pytorch
--args='-e TensorFlow' # TensorFlow
--args='-e PyTorch' # PyTorch
--args='-e MXNet' # Apache MXNet
--args='-e PaddlePaddle' # PaddlePaddle
--args='-e OnnxRuntime' # pytorch
--args='-e TFLite' # TFLite
--args='-e DLR' # Neo DLR
--args='-e XGBoost' # XGBoost
```
to change your default engine.

### Step 2: Identify the source of your model

DJL accept variety of models came from different places.

#### Remote location

Use `--model-url` option to load a model from a URL. The URL must point to an archive file.

The following is a pytorch model

```
-Dai.djl.repository.zoo.location=https://alpha-djl-demos.s3.amazonaws.com/model/djl-blockrunner/pytorch_resnet18.zip
--args='-u https://alpha-djl-demos.s3.amazonaws.com/model/djl-blockrunner/pytorch_resnet18.zip'
```
We would recommend to make model files in a zip for better file tracking.

#### Local directory

Use `--model-path` option to load model from a local directory or an archive file.

Mac/Linux

```
Expand All @@ -143,29 +153,12 @@ or
```

If the model file name is different from the parent folder name (or the archive file name), you need
to specify `-n MODEL_NAME` in the `--args`:
to specify `--model-name` in the `--args`:

```
--args='-n traced_resnet18'
```

#### DJL Model zoo

You can run `listmodels` to list available models that you can use from different model zoos.

```
./gradlew listmodels # MXNet models
./gradlew listmodels -Dai.djl.default_engine=TensorFlow # TensorFlow models
./gradlew listmodels -Dai.djl.default_engine=PyTorch # PyTorch models
```

After that, just simply copy the json formatted criteria like `{"layers":"18","flavor":"v1","dataset":"imagenet"}` with the artifact id like `ai.djl.mxnet:resnet:0.0.1`.
Then, you can just pass the information in the `--args` (remove `0.0.1` at the end):

```
-a ai.djl.mxnet:resnet -r {"layers":"18","flavor":"v1","dataset":"imagenet"}
```

### Step 3: Define how many runs you would like to make

add `-c` inside with a number
Expand All @@ -178,7 +171,7 @@ This will run 1000 times inference.

### Step 4: Define your model inputs

The benchmark script support dummy NDArray inputs.
The benchmark script uses dummy NDArray inputs.
It will make fake NDArrays (like `NDArray.ones`) to feed in the model for inference.

If we would like to fake an image:
Expand Down Expand Up @@ -212,7 +205,7 @@ For example:
-s (1)i,(384)f,(384)
```

### Optional Step: multithreading inference
### Optional Step: multithreading inference

You can also do multi-threading inference with DJL. For example, if you would like to run the inference with 10 threads:

Expand All @@ -234,10 +227,10 @@ The above code will create 10 threads with the wait time of 100ms.
For different purposes, we designed different mode you can play with. Such as the following arg:

```
-d 1440
-d 86400
```

This will ask the benchmark script repeatly running the designed task for 1440 minutes (24 hour).
This will ask the benchmark script repeatedly running the designed task for 86400 seconds (24 hour).
If you would like to make sure DJL is stable in the long run, you can do that.

You can also keep monitoring the DJL memory usages by enable the following flag:
Expand Down
110 changes: 110 additions & 0 deletions extensions/benchmark/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
plugins {
id 'application'
}

dependencies {
implementation "commons-cli:commons-cli:${commons_cli_version}"
implementation "org.apache.logging.log4j:log4j-slf4j-impl:${log4j_slf4j_version}"
implementation project(":model-zoo")

runtimeOnly project(":pytorch:pytorch-model-zoo")
runtimeOnly "ai.djl.pytorch:pytorch-native-auto:1.8.1"

// javacpp bug fix https://github.com/bytedeco/javacpp/commit/7f27899578dfa18e22738a3dd49701e1806b464a
runtimeOnly "org.bytedeco:javacpp:1.5.6-SNAPSHOT"
runtimeOnly(project(":tensorflow:tensorflow-model-zoo")) {
exclude group: "org.bytedeco", module: "javacpp"
}
runtimeOnly "ai.djl.tensorflow:tensorflow-native-auto:${tensorflow_version}"

runtimeOnly project(":mxnet:mxnet-model-zoo")
runtimeOnly "ai.djl.mxnet:mxnet-native-auto:${mxnet_version}"

runtimeOnly project(":tflite:tflite-engine")
runtimeOnly "ai.djl.tflite:tflite-native-auto:${tflite_version}"

runtimeOnly project(":paddlepaddle:paddlepaddle-model-zoo")
runtimeOnly "ai.djl.paddlepaddle:paddlepaddle-native-auto:${paddlepaddle_version}"

// onnxruntime requires user install libgomp.so.1 manually, exclude from default dependency
runtimeOnly project(":onnxruntime:onnxruntime-engine")

runtimeOnly project(":dlr:dlr-engine")
runtimeOnly "ai.djl.dlr:dlr-native-auto:${dlr_version}"

runtimeOnly(project(":ml:xgboost")) {
exclude group: "ml.dmlc", module: "xgboost4j_2.12"
}

testImplementation("org.testng:testng:${testng_version}") {
exclude group: "junit", module: "junit"
}
}

application {
mainClassName = System.getProperty("main", "ai.djl.benchmark.Benchmark")
}

run {
environment("TF_CPP_MIN_LOG_LEVEL", "1") // turn off TensorFlow print out
systemProperties System.getProperties()
systemProperties.remove("user.dir")
systemProperty("file.encoding", "UTF-8")
}

task benchmark(type: JavaExec) {
environment("TF_CPP_MIN_LOG_LEVEL", "1") // turn off TensorFlow print out
List<String> arguments = gradle.startParameter["taskRequests"]["args"].getAt(0)
for (String argument : arguments) {
if (argument.trim().startsWith("--args")) {
String[] line = argument.split("=", 2)
if (line.length == 2) {
line = line[1].split(" ")
if (line.contains("-t")) {
if (System.getProperty("ai.djl.default_engine") == "TensorFlow") {
environment("OMP_NUM_THREADS", "1")
environment("TF_NUM_INTRAOP_THREADS", "1")
} else {
environment("MXNET_ENGINE_TYPE", "NaiveEngine")
environment("OMP_NUM_THREADS", "1")
}
}
break
}
}
}

systemProperties System.getProperties()
systemProperties.remove("user.dir")
systemProperty("file.encoding", "UTF-8")
classpath = sourceSets.main.runtimeClasspath
// restrict the jvm heap size for better monitoring benchmark
jvmArgs = ["-Xmx2g"]
if (Boolean.getBoolean("loggc")) {
if (JavaVersion.current() == JavaVersion.VERSION_1_8) {
jvmArgs += ["-XX:+PrintGCTimeStamps", "-Xloggc:build/gc.log"]
} else {
jvmArgs += ["-Xlog:gc*=debug:file=build/gc.log"]
}
}
main = "ai.djl.benchmark.Benchmark"
}

startScripts {
defaultJvmOpts = []
doLast {
String replacement = 'CLASSPATH=\\$APP_HOME/lib/*\n\n' +
'if [[ "\\$*" == *-t* || "\\$*" == *--threads* ]]\n' +
'then\n' +
' export TF_CPP_MIN_LOG_LEVEL=1\n' +
' export MXNET_ENGINE_TYPE=NaiveEngine\n' +
' export OMP_NUM_THREADS=1\n' +
' export TF_NUM_INTRAOP_THREADS=1\n' +
'fi'

String text = unixScript.text.replaceAll('CLASSPATH=\\$APP_HOME/lib/.*', replacement)
unixScript.text = text
}
}

tasks.distZip.enabled = false
Loading

0 comments on commit 5f85fcc

Please sign in to comment.