Skip to content

Commit a47cc65

Browse files
authored
E2E benchmark tests (#269)
Uses `pytest-benchmark` to perform E2E benchmarks on the following workflows: - SID NLP - Phishing Detection NLP - ABP FIL - HAMMAH Input for these tests are pulled from LFS data already included in this repo. Hook is used to add the following information to the output JSON: GPU: ``` "gpu_0": { "id": 0, "name": "Quadro RTX 8000", "load": "0.0%", "free_memory": "42444.0MB", "used_memory": "6156.0MB", "temperature": "61.0 C", "uuid": "GPU-dc32de82-bdaa-2d05-2abe-260a847e1989" } ``` Morpheus config for each workflow: - num_threads - pipeline_batch_size - model_max_batch_size - feature_length - edge_buffer_size Additional benchmark stats for each workflow: - input_lines - min_throughput_lines - max_throughput_lines - mean_throughput_lines - median_throughput_lines - input_bytes - min_throughput_bytes - max_throughput_bytes - mean_throughput_bytes - median_throughput_bytes Thoughputs were calculated by dividing input lines/bytes by total runtimes. ~These calculations will be replaced using tracer implementation developed by @drobison00.~ Tracer will be added in a separate PR. Authors: - Eli Fajardo (https://github.com/efajardo-nv) Approvers: - Michael Demoret (https://github.com/mdemoret-nv) URL: #269
1 parent f2dd0e8 commit a47cc65

File tree

6 files changed

+419
-0
lines changed

6 files changed

+419
-0
lines changed

ci/conda/recipes/morpheus/meta.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ outputs:
8585
test:
8686
requires:
8787
- cudatoolkit {{ cuda_version }}.*
88+
- gputil
8889
- pytest
8990
- pytest-cov
9091
- pytest-benchmark

docker/conda/environments/cuda11.5_dev.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ dependencies:
4545
- git>=2.35.3 # Needed for wildcards on safe.directory
4646
- glog=0.6
4747
- gmock=1.10
48+
- gputil
4849
- grpc-cpp>=1.43
4950
- gtest=1.10
5051
- gxx_linux-64=9.4

tests/benchmarks/README.md

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
<!--
2+
# Copyright (c) 2021-2022, NVIDIA CORPORATION.
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
-->
16+
17+
# Running E2E Benchmarks
18+
19+
### Set up Triton Inference Server
20+
21+
##### Pull Triton Inference Server Docker Image
22+
Pull Docker image from NGC (https://ngc.nvidia.com/catalog/containers/nvidia:tritonserver) suitable for your environment.
23+
24+
Example:
25+
26+
```
27+
docker pull nvcr.io/nvidia/tritonserver:22.02-py3
28+
```
29+
30+
##### Start Triton Inference Server container
31+
```
32+
cd ${MORPHEUS_ROOT}/models
33+
34+
docker run --gpus=1 --rm -p8000:8000 -p8001:8001 -p8002:8002 -v $PWD:/models nvcr.io/nvidia/tritonserver:22.06-py3 tritonserver --model-repository=/models/triton-model-repo --model-control-mode=explicit --load-model sid-minibert-onnx --load-model abp-nvsmi-xgb --load-model phishing-bert-onnx
35+
```
36+
37+
##### Verify Model Deployments
38+
Once Triton server finishes starting up, it will display the status of all loaded models. Successful deployment of the model will show the following:
39+
40+
```
41+
+--------------------+---------+--------+
42+
| Model | Version | Status |
43+
+--------------------+---------+--------+
44+
| abp-nvsmi-xgb | 1 | READY |
45+
| phishing-bert-onnx | 1 | READY |
46+
| sid-minibert-onnx | 1 | READY |
47+
+--------------------+---------+--------+
48+
```
49+
50+
### Run E2E Benchmarks
51+
52+
Benchmarks are run using `pytest-benchmark`. Benchmarks for an individual workflow can be run using the following:
53+
54+
```
55+
cd tests/benchmarks
56+
57+
pytest -s --benchmark-enable --benchmark-autosave test_bench_e2e_pipelines.py::<test-workflow>
58+
```
59+
The `-s` option allows outputs of pipeline execution to be displayed so you can ensure there are no errors while running your benchmarks.
60+
61+
`<test-workflow>` is the name of the test to run benchmarks on. This can be `test_sid_nlp_e2e`, `test_abp_fil_e2e`, `test_phishing_nlp_e2e` or `test_cloudtrail_ae_e2e`.
62+
63+
For example, to run E2E benchmarks on the SID NLP workflow:
64+
```
65+
pytest -s --benchmark-enable --benchmark-autosave test_bench_e2e_pipelines.py::test_sid_nlp_e2e
66+
```
67+
68+
To run E2E benchmarks on all workflows:
69+
```
70+
pytest -s --benchmark-enable --benchmark-autosave test_bench_e2e_pipelines.py
71+
```
72+
73+
The console output should look like this:
74+
```
75+
------------------------------------------------------------------------------------------- benchmark: 4 tests ------------------------------------------------------------------------------------------
76+
Name (time in ms) Min Max Mean StdDev Median IQR Outliers OPS Rounds Iterations
77+
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
78+
test_phishing_nlp_e2e 834.5413 (1.0) 892.8774 (1.0) 858.9724 (1.0) 22.5832 (1.0) 854.7082 (1.0) 31.7465 (1.0) 2;0 1.1642 (1.0) 5 1
79+
test_sid_nlp_e2e 2,055.0733 (2.46) 2,118.1255 (2.37) 2,095.8951 (2.44) 26.2586 (1.16) 2,105.8771 (2.46) 38.5301 (1.21) 1;0 0.4771 (0.41) 5 1
80+
test_abp_fil_e2e 5,016.7639 (6.01) 5,292.9841 (5.93) 5,179.0901 (6.03) 121.5466 (5.38) 5,195.2253 (6.08) 215.2213 (6.78) 1;0 0.1931 (0.17) 5 1
81+
test_cloudtrail_ae_e2e 6,929.7436 (8.30) 7,157.0487 (8.02) 6,995.1969 (8.14) 92.8935 (4.11) 6,971.9611 (8.16) 87.2056 (2.75) 1;1 0.1430 (0.12) 5 1
82+
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
83+
```
84+
85+
A comprehensive report for each test run will be saved to a JSON file in `./tests/benchmarks/.benchmarks`. This will include throughput (lines/sec, bytes/sec), GPU info and Morpheus configs for each test workflow.

tests/benchmarks/conftest.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
16+
import glob
17+
import os
18+
19+
import GPUtil
20+
from test_bench_e2e_pipelines import E2E_TEST_CONFIGS
21+
22+
23+
def pytest_benchmark_update_json(config, benchmarks, output_json):
24+
25+
gpus = GPUtil.getGPUs()
26+
27+
for i, gpu in enumerate(gpus):
28+
# output_json["machine_info"]["gpu_" + str(i)] = gpu.name
29+
output_json["machine_info"]["gpu_" + str(i)] = {}
30+
output_json["machine_info"]["gpu_" + str(i)]["id"] = gpu.id
31+
output_json["machine_info"]["gpu_" + str(i)]["name"] = gpu.name
32+
output_json["machine_info"]["gpu_" + str(i)]["load"] = f"{gpu.load*100}%"
33+
output_json["machine_info"]["gpu_" + str(i)]["free_memory"] = f"{gpu.memoryFree}MB"
34+
output_json["machine_info"]["gpu_" + str(i)]["used_memory"] = f"{gpu.memoryUsed}MB"
35+
output_json["machine_info"]["gpu_" + str(i)]["temperature"] = f"{gpu.temperature} C"
36+
output_json["machine_info"]["gpu_" + str(i)]["uuid"] = gpu.uuid
37+
38+
line_count = 0
39+
byte_count = 0
40+
for bench in output_json['benchmarks']:
41+
if "file_path" in E2E_TEST_CONFIGS[bench["name"]]:
42+
source_file = E2E_TEST_CONFIGS[bench["name"]]["file_path"]
43+
line_count = len(open(source_file).readlines())
44+
byte_count = os.path.getsize(source_file)
45+
46+
elif "glob_path" in E2E_TEST_CONFIGS[bench["name"]]:
47+
for fn in glob.glob(E2E_TEST_CONFIGS[bench["name"]]["glob_path"]):
48+
line_count += len(open(fn).readlines())
49+
byte_count += os.path.getsize(fn)
50+
51+
repeat = E2E_TEST_CONFIGS[bench["name"]]["repeat"]
52+
53+
bench["morpheus_config"] = {}
54+
bench["morpheus_config"]["num_threads"] = E2E_TEST_CONFIGS[bench["name"]]["num_threads"]
55+
bench["morpheus_config"]["pipeline_batch_size"] = E2E_TEST_CONFIGS[bench["name"]]["pipeline_batch_size"]
56+
bench["morpheus_config"]["model_max_batch_size"] = E2E_TEST_CONFIGS[bench["name"]]["model_max_batch_size"]
57+
bench["morpheus_config"]["feature_length"] = E2E_TEST_CONFIGS[bench["name"]]["feature_length"]
58+
bench["morpheus_config"]["edge_buffer_size"] = E2E_TEST_CONFIGS[bench["name"]]["edge_buffer_size"]
59+
60+
bench['stats']["input_lines"] = line_count * repeat
61+
bench['stats']['min_throughput_lines'] = (line_count * repeat) / bench['stats']['max']
62+
bench['stats']['max_throughput_lines'] = (line_count * repeat) / bench['stats']['min']
63+
bench['stats']['mean_throughput_lines'] = (line_count * repeat) / bench['stats']['mean']
64+
bench['stats']['median_throughput_lines'] = (line_count * repeat) / bench['stats']['median']
65+
bench['stats']["input_bytes"] = byte_count * repeat
66+
bench['stats']['min_throughput_bytes'] = (byte_count * repeat) / bench['stats']['max']
67+
bench['stats']['max_throughput_bytes'] = (byte_count * repeat) / bench['stats']['min']
68+
bench['stats']['mean_throughput_bytes'] = (byte_count * repeat) / bench['stats']['mean']
69+
bench['stats']['median_throughput_bytes'] = (byte_count * repeat) / bench['stats']['median']
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
{
2+
"triton_server_url": "localhost:8001",
3+
"test_sid_nlp_e2e": {
4+
"file_path": "../../models/datasets/validation-data/sid-validation-data.csv",
5+
"repeat": 10,
6+
"num_threads": 8,
7+
"pipeline_batch_size": 1024,
8+
"model_max_batch_size": 64,
9+
"feature_length": 256,
10+
"edge_buffer_size": 4
11+
},
12+
"test_abp_fil_e2e": {
13+
"file_path": "../../models/datasets/validation-data/abp-validation-data.jsonlines",
14+
"repeat": 100,
15+
"num_threads": 8,
16+
"pipeline_batch_size": 1024,
17+
"model_max_batch_size": 1024,
18+
"feature_length": 29,
19+
"edge_buffer_size": 4
20+
},
21+
"test_phishing_nlp_e2e": {
22+
"file_path": "../../models/datasets/validation-data/phishing-email-validation-data.jsonlines",
23+
"repeat": 10,
24+
"num_threads": 8,
25+
"pipeline_batch_size": 1024,
26+
"model_max_batch_size": 64,
27+
"feature_length": 128,
28+
"edge_buffer_size": 4
29+
},
30+
"test_cloudtrail_ae_e2e": {
31+
"glob_path": "../../models/datasets/validation-data/hammah-*.csv",
32+
"repeat": 1,
33+
"num_threads": 1,
34+
"pipeline_batch_size": 1024,
35+
"model_max_batch_size": 1024,
36+
"feature_length": 32,
37+
"edge_buffer_size": 4
38+
}
39+
}

0 commit comments

Comments
 (0)