Skip to content

Commit 28da6a8

Browse files
Jiseong-ohchong-chen01jonghun-cha
authored
Enable Exynosbackend e2e test (#15731)
### Summary Enable E2E test for the Exynos backend. Modify it to run the testing using a device from devicefarm that can be used directly in CI. ### Test plan Each test case was verified on a real device. cc @SS-JIA @digantdesai @kimishpatel --------- Signed-off-by: jiseong.oh <jiseong.oh@samsung.com> Co-authored-by: chong-chen <chong.chen@samsung.com> Co-authored-by: Jonghun Cha <jhbb.cha@samsung.com>
1 parent 02682bc commit 28da6a8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+822
-97
lines changed

.ci/scripts/setup-samsung-linux-deps.sh

Lines changed: 175 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -8,61 +8,199 @@
88

99
set -ex
1010

11+
API_KEY=$SAMSUNG_AI_LITECORE_KEY
12+
if [[ -z "${API_KEY}" ]]; then
13+
echo "ERROR: It didn't set up SAMSUNG_AI_LITECORE_KEY." >&2
14+
exit 1
15+
fi
16+
17+
OS_NAME="Ubuntu 22.04"
18+
LITECORE_BASE="https://soc-developer.semiconductor.samsung.com/api/v1/resource/ai-litecore/download"
19+
DEVICEFARM_BASE="https://soc-developer.semiconductor.samsung.com/api/v1/resource/remotelab/download"
20+
21+
parse_url() {
22+
local json="$1"
23+
if command -v jq >/dev/null 2>&1; then
24+
jq -r '.data // empty' <<<"$json"
25+
else
26+
sed -n 's/.*"data":[[:space:]]*"\([^"]*\)".*/\1/p' <<<"$json"
27+
fi
28+
}
1129

12-
download_ai_lite_core() {
13-
API_BASE="https://soc-developer.semiconductor.samsung.com/api/v1/resource/ai-litecore/download"
14-
API_KEY=$SAMSUNG_AI_LITECORE_KEY
15-
16-
VERSION="0.7"
17-
OS_NAME="Ubuntu 22.04"
18-
OUT_FILE="/tmp/exynos-ai-litecore-v${VERSION}.tar.gz"
19-
TARGET_PATH="/tmp/exynos_ai_lite_core"
20-
21-
mkdir -p ${TARGET_PATH}
22-
# Presigned issue URL
23-
JSON_RESP=$(curl -sS -G \
24-
--location --fail --retry 3 \
30+
download_and_extract() {
31+
local base_url="$1"
32+
local version="$2"
33+
local out_dir="$3"
34+
local out_file="$4"
35+
36+
local resp
37+
resp=$(curl -fsSL -G \
2538
-H "apikey: ${API_KEY}" \
26-
--data-urlencode "version=${VERSION}" \
39+
--data-urlencode "version=${version}" \
2740
--data-urlencode "os=${OS_NAME}" \
28-
"${API_BASE}")
41+
"${base_url}")
42+
43+
local download_url
44+
download_url=$(parse_url "$resp")
45+
if [[ -z "${download_url}" ]]; then
46+
echo "ERROR: It failed to download from ${base_url} ."
47+
echo "Response: $resp" >&2
48+
exit 1
49+
fi
50+
51+
curl -fsSL -L --retry 3 -o "${out_file}" "${download_url}"
52+
echo "Download completed: ${out_file}"
2953

30-
DOWNLOAD_URL=$(echo "$JSON_RESP" | sed -n 's/.*"data":[[:space:]]*"\([^"]*\)".*/\1/p')
54+
mkdir -p "${out_dir}"
55+
case "${out_file##*.}" in
56+
tar|tgz|gz)
57+
echo "Extracting TAR.GZ..."
58+
tar -C "${out_dir}" --strip-components=1 -xzvf "${out_file}"
59+
;;
3160

32-
if [[ -z "$DOWNLOAD_URL" ]]; then
33-
echo "Failed to extract download URL"
34-
echo "$JSON_RESP"
61+
zip)
62+
echo "Extracting ZIP..."
63+
unzip -q -d "${out_dir}" "${out_file}"
64+
;;
65+
66+
*)
3567
exit 1
68+
;;
69+
esac
70+
echo "Extracted to: ${out_dir}"
71+
}
72+
73+
download_ai_lite_core() {
74+
local litecore_version="${1:-1.0}"
75+
local litecore_out="/tmp/exynos-ai-litecore-v${litecore_version}.tar.gz"
76+
local litecore_dir="/tmp/exynos_ai_lite_core"
77+
78+
download_and_extract \
79+
"${LITECORE_BASE}" \
80+
"${litecore_version}" \
81+
"${litecore_dir}" \
82+
"${litecore_out}"
83+
84+
export EXYNOS_AI_LITECORE_ROOT="${litecore_dir}"
85+
export LD_LIBRARY_PATH="${LD_LIBRARY_PATH:-}:${EXYNOS_AI_LITECORE_ROOT}/lib/x86_64-linux"
86+
}
87+
88+
install_devicefarm_cli() {
89+
local cli_version="${1:-beta-1.0.8}"
90+
local cli_out="/tmp/devicefarm-cli-v${cli_version}.zip"
91+
local cli_dir="/tmp/devicefarm_cli"
92+
93+
download_and_extract \
94+
"${DEVICEFARM_BASE}" \
95+
"${cli_version}" \
96+
"${cli_dir}" \
97+
"${cli_out}"
98+
99+
export PATH="${PATH%:}:${cli_dir}"
100+
chmod +x "${cli_dir}/devicefarm-cli"
101+
}
102+
103+
reserve_if_needed() {
104+
if ! command -v devicefarm-cli >/dev/null 2>&1; then
105+
echo "[WARN] devicefarm-cli is not installed." >&2
106+
return 1
36107
fi
37108

38-
# Download LiteCore
39-
curl -sS -L --fail --retry 3 \
40-
--output "$OUT_FILE" \
41-
"$DOWNLOAD_URL"
109+
local raw_info info_lines
110+
raw_info="$(devicefarm-cli -I)"
111+
112+
info_lines="$(printf '%s\n' "$raw_info" | grep -v '^\\[INFO\\]')"
42113

43-
echo "Download done: $OUT_FILE"
114+
local found_count
44115

116+
found_count=$(printf '%s\n' "$info_lines" \
117+
| grep -Eo 'Found available reservations *: *[0-9]+' \
118+
| grep -Eo '[0-9]+')
119+
[[ -z "$found_count" ]] && found_count=0
45120

46-
tar -C "${TARGET_PATH}" --strip-components=1 -xzvf "${OUT_FILE}"
121+
echo "[INFO] Current Reserved Count: $found_count"
122+
123+
local THRESHOLD_SECONDS=12600
124+
local any_below_threshold=0
125+
126+
if (( found_count > 0 )); then
127+
local table_body
128+
table_body=$(printf '%s\n' "$info_lines" | sed -n '2,$p')
129+
130+
while IFS= read -r line; do
131+
if [[ "$line" =~ ^[0-9]+[[:space:]]+([0-9]{1,2}:[0-9]{2}:[0-9]{2}) ]]; then
132+
local time_str="${BASH_REMATCH[1]}"
133+
IFS=: read -r hh mm ss <<<"$time_str"
134+
(( seconds = 10#$hh * 3600 + 10#$mm * 60 + 10#$ss ))
135+
if (( seconds <= THRESHOLD_SECONDS )); then
136+
any_below_threshold=1
137+
break
138+
fi
139+
fi
140+
done <<<"$table_body"
141+
else
142+
any_below_threshold=1
143+
fi
47144

48-
export EXYNOS_AI_LITECORE_ROOT=${TARGET_PATH}
49-
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH:-}:${EXYNOS_AI_LITECORE_ROOT}/lib/x86_64-linux
145+
if (( any_below_threshold )); then
146+
echo "[INFO] Reserving now."
147+
devicefarm-cli -R
148+
else
149+
echo "[INFO] Don't need to be reserved."
150+
fi
151+
152+
local info_after reservation_id max_seconds=0 max_id
153+
154+
info_after="$(devicefarm-cli -I)"
155+
156+
local body_after
157+
body_after=$(printf '%s\n' "$info_after" | grep -v '^\\[INFO\\]' | sed -n '2,$p')
158+
159+
while IFS= read -r line; do
160+
if [[ "$line" =~ ^[0-9]+[[:space:]]+([0-9]{1,2}:[0-9]{2}:[0-9]{2})[[:space:]].*([0-9a-f-]{36})$ ]]; then
161+
local time_str="${BASH_REMATCH[1]}"
162+
local id="${BASH_REMATCH[2]}"
163+
IFS=: read -r hh mm ss <<<"$time_str"
164+
(( seconds = 10#$hh * 3600 + 10#$mm * 60 + 10#$ss ))
165+
if (( seconds > max_seconds )); then
166+
max_seconds=$seconds
167+
max_id=$id
168+
fi
169+
fi
170+
done <<<"$body_after"
171+
172+
reservation_id=$max_id
173+
174+
if [[ -n "$reservation_id" ]]; then
175+
devicefarm-cli -C "$reservation_id"
176+
devicefarm-cli -E "ls /"
177+
else
178+
echo "[WARN] There is no available devices."
179+
fi
50180
}
51181

52182
install_enn_backend() {
53-
NDK_INSTALLATION_DIR=/opt/ndk
54-
rm -rf "${NDK_INSTALLATION_DIR}" && sudo mkdir -p "${NDK_INSTALLATION_DIR}"
55-
ANDROID_NDK_VERSION=r28c
183+
local ndk_dir="/opt/ndk"
184+
local ndk_version="r28c"
185+
186+
if [[ ! -d "${ndk_dir}" ]]; then
187+
sudo mkdir -p "${ndk_dir}"
188+
sudo chown "$(whoami)":"$(whoami)" "${ndk_dir}"
189+
fi
190+
191+
export ANDROID_NDK_ROOT="${ndk_dir}"
192+
echo "NDK will be installed/used at: ${ANDROID_NDK_ROOT}"
56193

57-
# build Exynos backend
58-
export ANDROID_NDK_ROOT=${ANDROID_NDK_ROOT:-/opt/ndk}
59194
bash backends/samsung/build.sh --build all
60-
# set env variable
61-
export EXECUTORCH_ROOT="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/../.." && pwd)"
62-
export PYTHONPATH=${PYTHONPATH:-}:${EXECUTORCH_ROOT}/..
195+
196+
export EXECUTORCH_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
197+
export PYTHONPATH="${PYTHONPATH:-}:${EXECUTORCH_ROOT}/.."
63198
}
64199

65-
AI_LITE_CORE_VERSION=0.7.0
200+
litecore_ver="1.0"
201+
devicefarm_ver="beta-1.0.8"
66202

67-
download_ai_lite_core ${AI_LITE_CORE_VERSION}
203+
download_ai_lite_core ${litecore_ver}
204+
install_devicefarm_cli "${devicefarm_ver}"
68205
install_enn_backend
206+
reserve_if_needed

.github/workflows/pull.yml

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -915,9 +915,8 @@ jobs:
915915
PYTHON_EXECUTABLE=python bash examples/nxp/run_aot_example.sh cifar10
916916
PYTHON_EXECUTABLE=python bash examples/nxp/run_aot_example.sh mobilenetv2
917917
918-
919-
test-samsung-models-linux:
920-
name: test-samsung-models-linux
918+
test-samsung-quantmodels-linux:
919+
name: test-samsung-quantmodels-linux
921920
# Skip this job if the pull request is from a fork (secrets are not available)
922921
if: github.event.pull_request.head.repo.full_name == github.repository || github.event_name != 'pull_request'
923922
uses: pytorch/test-infra/.github/workflows/linux_job_v2.yml@main
@@ -931,7 +930,7 @@ jobs:
931930
docker-image: ci-image:executorch-ubuntu-22.04-clang12-android
932931
submodules: 'recursive'
933932
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
934-
timeout: 90
933+
timeout: 180
935934
script: |
936935
set -ex
937936
@@ -946,21 +945,44 @@ jobs:
946945
export SAMSUNG_AI_LITECORE_KEY=$SECRET_SAMSUNG_AI_LITECORE_KEY
947946
source .ci/scripts/setup-samsung-linux-deps.sh
948947
949-
# Test models serially
950-
models="mv2 ic3 resnet18 resnet50 mv3 ic4 dl3 edsr vit w2l"
951-
for model in $models; do
952-
python -m executorch.examples.samsung.aot_compiler --model_name=$model -c E9955
953-
done
954-
955948
# Test quant models
956949
model_scripts="deeplab_v3 edsr inception_v3 inception_v4 mobilenet_v2 mobilenet_v3 resnet18 resnet50 vit wav2letter"
957950
for m_script in $model_scripts; do
958951
python -m executorch.examples.samsung.scripts.${m_script} -c e9955 -p A8W8
959952
done
960953
961-
# Test ops
962-
python -m unittest discover -s backends/samsung/test/ops -p "test_*.py"
954+
test-samsung-models-linux:
955+
name: test-samsung-models-linux
956+
# Skip this job if the pull request is from a fork (secrets are not available)
957+
if: github.event.pull_request.head.repo.full_name == github.repository || github.event_name != 'pull_request'
958+
uses: pytorch/test-infra/.github/workflows/linux_job_v2.yml@main
959+
permissions:
960+
id-token: write
961+
contents: read
962+
secrets: inherit
963+
with:
964+
secrets-env: SAMSUNG_AI_LITECORE_KEY
965+
runner: linux.2xlarge
966+
docker-image: ci-image:executorch-ubuntu-22.04-clang12-android
967+
submodules: 'recursive'
968+
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
969+
timeout: 360
970+
script: |
971+
set -ex
972+
973+
# The generic Linux job chooses to use base env, not the one setup by the image
974+
CONDA_ENV=$(conda env list --json | jq -r ".envs | .[-1]")
975+
conda activate "${CONDA_ENV}"
976+
977+
# Setup python
978+
PYTHON_EXECUTABLE=python bash .ci/scripts/setup-linux.sh --build-tool "cmake"
979+
980+
# Setup Samsung SDK (AI Lite Core) and install enn backend
981+
export SAMSUNG_AI_LITECORE_KEY=$SECRET_SAMSUNG_AI_LITECORE_KEY
982+
source .ci/scripts/setup-samsung-linux-deps.sh
963983
984+
# Test models
985+
python -m unittest discover -s backends/samsung/test/models -p "test_*.py"
964986
965987
test-vulkan-models-linux:
966988
name: test-vulkan-models-linux
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Copyright (c) Samsung Electronics Co. LTD
2+
# All rights reserved
3+
#
4+
# Licensed under the BSD License (the "License"); you may not use this file
5+
# except in compliance with the License. See the license file in the root
6+
# directory of this source tree for more details.
7+
import unittest
8+
9+
from executorch.backends.samsung.serialization.compile_options import (
10+
gen_samsung_backend_compile_spec,
11+
)
12+
from executorch.backends.samsung.test.tester import SamsungTester
13+
from executorch.examples.models.deeplab_v3 import DeepLabV3ResNet50Model
14+
15+
16+
class TestMilestoneDeepLabV3(unittest.TestCase):
17+
def test_dl3_fp16(self):
18+
model = DeepLabV3ResNet50Model().get_eager_model()
19+
example_input = DeepLabV3ResNet50Model().get_example_inputs()
20+
tester = SamsungTester(
21+
model, example_input, [gen_samsung_backend_compile_spec("E9955")]
22+
)
23+
(
24+
tester.export()
25+
.to_edge_transform_and_lower()
26+
.to_executorch()
27+
.run_method_and_compare_outputs(inputs=example_input, atol=0.009)
28+
)
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Copyright (c) Samsung Electronics Co. LTD
2+
# All rights reserved
3+
#
4+
# Licensed under the BSD License (the "License"); you may not use this file
5+
# except in compliance with the License. See the license file in the root
6+
# directory of this source tree for more details.
7+
8+
9+
import unittest
10+
11+
from executorch.backends.samsung.serialization.compile_options import (
12+
gen_samsung_backend_compile_spec,
13+
)
14+
from executorch.backends.samsung.test.tester import SamsungTester
15+
from executorch.examples.models.edsr import EdsrModel
16+
17+
18+
class TestMilestoneEdsr(unittest.TestCase):
19+
def test_edsr_fp16(self):
20+
model = EdsrModel().get_eager_model()
21+
example_input = EdsrModel().get_example_inputs()
22+
tester = SamsungTester(
23+
model, example_input, [gen_samsung_backend_compile_spec("E9955")]
24+
)
25+
(
26+
tester.export()
27+
.to_edge_transform_and_lower()
28+
.to_executorch()
29+
.run_method_and_compare_outputs(inputs=example_input, atol=0.02)
30+
)

0 commit comments

Comments
 (0)