Skip to content

Commit 4b174f8

Browse files
authored
Merge pull request #2 from KumarRobotics/feature/ci
add ci unit tests
2 parents 403b34d + 6b9b582 commit 4b174f8

5 files changed

Lines changed: 107 additions & 27 deletions

File tree

‎.github/workflows/tests.yml‎

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
name: Unit Tests
2+
3+
on:
4+
pull_request:
5+
branches: [main]
6+
push:
7+
branches: [main]
8+
workflow_dispatch:
9+
10+
permissions:
11+
contents: read
12+
13+
concurrency:
14+
group: unit-tests-${{ github.ref }}
15+
cancel-in-progress: true
16+
17+
env:
18+
IMAGE: sam3-tensorrt:infer
19+
20+
jobs:
21+
unit-tests:
22+
runs-on: [self-hosted, linux, gpu] # must match --labels used in config.sh
23+
timeout-minutes: 90
24+
25+
if: >-
26+
github.event_name != 'pull_request' ||
27+
github.event.pull_request.head.repo.full_name == github.repository
28+
29+
steps:
30+
- uses: actions/checkout@v4
31+
with:
32+
clean: false
33+
34+
- name: Build docker image
35+
working-directory: docker
36+
run: ./build-trt.bash
37+
38+
- name: Run unit tests in container
39+
env:
40+
MODELS_DIR: /home/jason/Projects/sam3-ws/SAM3-TensorRT/models
41+
TEST_SCRIPT: |
42+
set -uo pipefail
43+
rc=0
44+
45+
if ! ls "$HOME"/models/*.engine >/dev/null 2>&1; then
46+
echo "::error::No .engine files found in the mounted models dir"
47+
exit 1
48+
fi
49+
nvidia-smi || true
50+
51+
echo "::group::C++ build and tests"
52+
( cd "$HOME/sam3trt" \
53+
&& cmake -S . -B build -DSAM3TRT_BUILD_TESTS=ON -DSAM3TRT_BUILD_ROS=OFF \
54+
&& cmake --build build -j"$(nproc)" \
55+
&& ctest --test-dir build --output-on-failure -E Timing ) || rc=1
56+
echo "::endgroup::"
57+
58+
echo "::group::Python tests"
59+
( cd "$HOME" \
60+
&& pip install --user --break-system-packages --no-cache-dir ./sam3trtpy \
61+
&& cd sam3trtpy \
62+
&& python3 -m unittest discover -s tests -v ) || rc=1
63+
echo "::endgroup::"
64+
65+
exit $rc
66+
run: |
67+
U="$(whoami)"
68+
# Same mounts as docker/run-trt.bash, minus the interactive/X11 parts.
69+
docker run --rm \
70+
--gpus all \
71+
--ipc=host \
72+
--user "$(id -u):$(id -g)" \
73+
-e HOME="/home/$U" \
74+
-e TEST_SCRIPT \
75+
-v "$MODELS_DIR:/home/$U/models" \
76+
-v "$GITHUB_WORKSPACE/sam3trt:/home/$U/sam3trt" \
77+
-v "$GITHUB_WORKSPACE/sam3trtpy:/home/$U/sam3trtpy" \
78+
-w "/home/$U" \
79+
"$IMAGE" \
80+
bash -c "$TEST_SCRIPT"

‎docker/Dockerfile.trt‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ WORKDIR /home/$USER
3535

3636
RUN sudo apt install -y python3-pip
3737
RUN pip3 install --no-deps opencv-python-headless ultralytics
38+
RUN pip install --no-cache-dir ultralytics==8.4.121
39+
ENV LD_LIBRARY_PATH=/opt/hpcx/ucx/lib:/opt/hpcx/ucc/lib:${LD_LIBRARY_PATH}
40+
3841

3942
RUN sudo apt update \
4043
&& sudo apt install -y \

‎scripts/export_ultralytics_image_encoder.py‎

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -80,12 +80,6 @@ def patch_layernorm(model):
8080
def trace_and_export_image_encoder(model : torch.nn.Module, input : Any, engine_path : str, fp16 : bool) -> Tuple[torch.Tensor]:
8181
wrapper = ImageEncoderWrapper(model).to(DEVICE).eval()
8282

83-
predictor.setup_source(input)
84-
85-
for batch in predictor.dataset:
86-
input = predictor.preprocess(batch[1])
87-
break
88-
8983
print("[ImageEncoderExport] Tracing Image Encoder Model")
9084
torch_output = wrapper(input) # warm up
9185
exp_program = torch.export.export(wrapper, (input,), strict=False)
@@ -223,16 +217,17 @@ def export_and_verify_image_encoder(predictor : SAM3SemanticPredictor, fp16 : bo
223217

224218
precision = "fp16" if fp16 else "fp32"
225219
engine_path = os.path.join(os.environ["HOME"], "models", f"image_encoder_{precision}.engine")
226-
#_ = trace_and_export_image_encoder(
227-
# predictor.model,
228-
# img,
229-
# engine_path,
230-
# fp16
231-
#)
232220

233221
for batch in predictor.dataset:
234222
im = predictor.preprocess(batch[1])
235223
break
224+
_ = trace_and_export_image_encoder(
225+
predictor.model,
226+
im,
227+
engine_path,
228+
fp16
229+
)
230+
236231
_verify_engine(engine_path, im, torch_output, min_cos=0.999 if fp16 else 0.9999)
237232

238233
return torch_output
@@ -255,15 +250,16 @@ def export_and_verify_image_encoder(predictor : SAM3SemanticPredictor, fp16 : bo
255250

256251
precision = "fp16" if args.fp16 else "fp32"
257252
engine_path = os.path.join(os.environ["HOME"], "models", f"image_encoder_{precision}.engine")
253+
254+
for batch in predictor.dataset:
255+
im = predictor.preprocess(batch[1])
256+
break
258257
_ = trace_and_export_image_encoder(
259258
predictor.model,
260-
img,
259+
im,
261260
engine_path,
262261
args.fp16
263262
)
264263

265-
for batch in predictor.dataset:
266-
im = predictor.preprocess(batch[1])
267-
break
268264
_verify_engine(engine_path, im, torch_output, min_cos=0.999 if args.fp16 else 0.9999)
269265

‎scripts/export_ultralytics_mask_decoder.py‎

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ def trace_and_export_mask_deocder(model : torch.nn.Module, input : Any, engine_p
238238
print("[MaskDecoderExport] Patching Mask Decoder Model")
239239
_, _, spatial_shapes, _ = fusion_wrapper(*input)
240240
H, W = int(spatial_shapes[0, 0]), int(spatial_shapes[0, 1])
241-
patch_rpb(predictor.model, H, W)
241+
patch_rpb(model, H, W)
242242

243243
torch_output = wrapper(*input)
244244

@@ -256,9 +256,10 @@ def trace_and_export_mask_deocder(model : torch.nn.Module, input : Any, engine_p
256256
offload_module_to_cpu=True,
257257
device=torch_tensorrt.Device("cuda:0"),
258258
)
259+
model.to(DEVICE) # offload_module_to_cpu leaves the weights on the CPU
259260

260-
#with open(engine_path, "wb") as f:
261-
# f.write(engine_bytes)
261+
with open(engine_path, "wb") as f:
262+
f.write(engine_bytes)
262263

263264
return torch_output
264265

@@ -376,12 +377,12 @@ def export_and_verify_mask_decoder(predictor : SAM3SemanticPredictor, input : Tu
376377

377378
precision = "fp16" if fp16 else "fp32"
378379
engine_path = os.path.join(os.environ["HOME"], "models", f"mask_decoder_{precision}.engine")
379-
#trace_and_export_mask_deocder(
380-
# predictor.model,
381-
# input,
382-
# engine_path,
383-
# fp16
384-
#)
380+
trace_and_export_mask_deocder(
381+
predictor.model,
382+
input,
383+
engine_path,
384+
fp16
385+
)
385386
predictor.set_image(img)
386387
ref = predictor(text=captions)[0]
387388
for batch in predictor.dataset:

‎scripts/export_ultralytics_text_encoder.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ def trace_and_export_text_encoder(model : torch.nn.Module, input : Any, engine_p
7979
exp_program,
8080
arg_inputs=[input[0].to(DEVICE), input[1].to(DEVICE)],
8181
optimization_level=5,
82-
use_explicit_typeing=True,
82+
use_explicit_typing=True,
8383
device=torch_tensorrt.Device(f"cuda:0"),
8484
)
8585

@@ -184,7 +184,7 @@ def export_and_verify_text_encoder(predictor : SAM3SemanticPredictor, fp16 : boo
184184

185185
precision = "fp16" if fp16 else "fp32"
186186
engine_path = os.path.join(os.environ["HOME"], "models", f"text_encoder_{precision}.engine")
187-
#trace_and_export_text_encoder(predictor.model, (input_ids, attention_mask), engine_path, args.fp16)
187+
trace_and_export_text_encoder(predictor.model, (input_ids, attention_mask), engine_path, fp16)
188188

189189
_verify_engine(engine_path, (input_ids, attention_mask), (torch_output[0], torch_output[2]), 0.999 if fp16 else 0.9999)
190190

0 commit comments

Comments
 (0)