Skip to content

Commit 0373307

Browse files
authored
[executorch][ci] Test Muse Glimmer batching on CUDA in OSS CI (#24010)
This PR was created by the merge bot to help merge the original PR into the main branch. ghstack PR number: #23818 by @Gasoonjia ^ Please use this as the source of truth for the PR details, comments, and reviews ghstack PR base: https://github.com/pytorch/executorch/tree/gh/Gasoonjia/58/base ghstack PR head: https://github.com/pytorch/executorch/tree/gh/Gasoonjia/58/head Merge bot PR base: https://github.com/pytorch/executorch/tree/gh/Gasoonjia/49/orig Merge bot PR head: https://github.com/pytorch/executorch/tree/gh/Gasoonjia/58/orig Differential Revision: [D124871963](https://our.internmc.facebook.com/intern/diff/D124871963/) @diff-train-skip-merge
1 parent dfdd5db commit 0373307

12 files changed

Lines changed: 1149 additions & 8 deletions

‎.ci/scripts/BUCK‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
load("@fbsource//tools/build_defs:fb_native_wrapper.bzl", "fb_native")
2+
3+
oncall("executorch")
4+
5+
# CMake builds this CI-only tool; group its sources without a product target.
6+
fb_native.filegroup(
7+
name = "muse_glimmer_batching_smoke_sources",
8+
srcs = [
9+
"muse_glimmer_batching_smoke.cpp",
10+
"muse_glimmer_batching_workload.h",
11+
"tests/muse_glimmer_batching_workload_test.cpp",
12+
],
13+
)
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#!/bin/bash
2+
# Copyright (c) Meta Platforms, Inc. and affiliates.
3+
# All rights reserved.
4+
#
5+
# This source code is licensed under the BSD-style license found in the
6+
# LICENSE file in the root directory of this source tree.
7+
8+
# Run after the normal batching build; reuse its backend and package settings.
9+
set -euo pipefail
10+
ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)
11+
BUILD_DIR="${1:-${ROOT}/cmake-out/examples/models/muse-glimmer-batching}"
12+
cmake -S "${ROOT}/examples/models/muse-glimmer" -B "$BUILD_DIR" \
13+
-DMUSE_GLIMMER_BUILD_BATCHING=ON -DMUSE_GLIMMER_BUILD_CI_SMOKE=ON
14+
cmake --build "$BUILD_DIR" --target muse_glimmer_batching_smoke --parallel

‎.ci/scripts/export_model_artifact.sh‎

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ Arguments:
5050
- vr-streaming: Voxtral Realtime streaming mode
5151
- vr-offline: Voxtral Realtime offline mode
5252
- solo-text: Muse Glimmer solo text mode
53+
- solo-text-batching: Muse Glimmer text on the CUDA batching runtime
5354
- dflash-image: Muse Glimmer DFlash vision mode
5455
5556
Examples:
@@ -104,7 +105,7 @@ if [ -n "$MODE" ]; then
104105
exit 1
105106
fi
106107
;;
107-
solo-text|dflash-image)
108+
solo-text|solo-text-batching|dflash-image)
108109
if [ "$HF_MODEL" != "meta-models/Muse-Glimmer-30B-GGUF" ]; then
109110
echo "Error: Mode '$MODE' can only be used with Muse Glimmer model"
110111
echo "Provided model: $HF_MODEL"
@@ -113,7 +114,7 @@ if [ -n "$MODE" ]; then
113114
;;
114115
*)
115116
echo "Error: Unsupported mode '$MODE'"
116-
echo "Supported modes: vr-streaming, vr-offline, solo-text, dflash-image"
117+
echo "Supported modes: vr-streaming, vr-offline, solo-text, solo-text-batching, dflash-image"
117118
exit 1
118119
;;
119120
esac
@@ -353,8 +354,8 @@ if [ "$MODEL_NAME" = "muse_glimmer" ]; then
353354
echo "Error: Muse Glimmer requires quantization 'kquant-17gb' or 'kquant-dynamic'"
354355
exit 1
355356
fi
356-
if [ "$MODE" != "solo-text" ] && [ "$MODE" != "dflash-image" ]; then
357-
echo "Error: Muse Glimmer requires mode 'solo-text' or 'dflash-image'"
357+
if [ "$MODE" != "solo-text" ] && [ "$MODE" != "solo-text-batching" ] && [ "$MODE" != "dflash-image" ]; then
358+
echo "Error: Muse Glimmer requires mode 'solo-text', 'solo-text-batching' or 'dflash-image'"
358359
exit 1
359360
fi
360361
fi
@@ -706,6 +707,18 @@ if [ "$MODEL_NAME" = "muse_glimmer" ]; then
706707
--backend cuda \
707708
--output-dir "${OUTPUT_DIR}"
708709
;;
710+
solo-text-batching)
711+
# The off-graph cache exports the batching methods CudaExecutor drives:
712+
# Static forward_{N}, dynamic forward_others and the device samplers.
713+
EXPORT_START_SECONDS=$SECONDS
714+
TMPDIR="$INDUCTOR_TMPDIR" \
715+
TORCHINDUCTOR_CACHE_DIR="$INDUCTOR_CACHE" \
716+
python -m executorch.examples.models.muse_glimmer.export.export_solo \
717+
--gguf "$TARGET_GGUF_PATH" \
718+
--backend cuda \
719+
--use-offgraph-kv-cache \
720+
--output-dir "${OUTPUT_DIR}"
721+
;;
709722
dflash-image)
710723
DRAFT_GGUF_FILE="dflash-Muse-Glimmer-30B-Q4_K_M.gguf"
711724
MMPROJ_GGUF_FILE="mmproj-Muse-Glimmer-30B-Q4_K_M.gguf"
@@ -722,7 +735,7 @@ if [ "$MODEL_NAME" = "muse_glimmer" ]; then
722735
--output-dir "${OUTPUT_DIR}"
723736
;;
724737
*)
725-
echo "Error: Muse Glimmer requires mode 'solo-text' or 'dflash-image'"
738+
echo "Error: Muse Glimmer requires mode 'solo-text', 'solo-text-batching' or 'dflash-image'"
726739
exit 1
727740
;;
728741
esac
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the BSD-style license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
*/
8+
#include "muse_glimmer_batching_workload.h"
9+
10+
#include <executorch/examples/models/muse-glimmer/runtime/backend_factory.h>
11+
#include <gflags/gflags.h>
12+
#include <pytorch/tokenizers/hf_tokenizer.h>
13+
14+
#include <iostream>
15+
#include <stdexcept>
16+
#include <string>
17+
#include <utility>
18+
19+
DECLARE_string(pte);
20+
DECLARE_string(tokenizer);
21+
DECLARE_string(data_path);
22+
DECLARE_string(backend);
23+
DECLARE_int32(max_sessions);
24+
DECLARE_int32(max_session_tokens);
25+
DECLARE_uint64(bos_id);
26+
27+
DEFINE_string(mode, "requests", "Correctness workload: requests");
28+
DEFINE_int32(requests, 8, "Number of concurrent requests");
29+
DEFINE_int32(prompt_tokens, 512, "Prompt positions including BOS per request");
30+
DEFINE_int32(max_new_tokens, 128, "Exact completion budget per request");
31+
DEFINE_int32(stagger_ms, 0, "Delay between request submissions");
32+
DEFINE_int32(max_decode, 32, "Maximum decodes admitted per step");
33+
DEFINE_int32(timeout_s, 600, "Request workload deadline");
34+
35+
int main(int argc, char** argv) {
36+
gflags::ParseCommandLineFlags(&argc, &argv, true);
37+
try {
38+
namespace llm = ::executorch::extension::llm;
39+
namespace ci = muse_glimmer_ci;
40+
if (FLAGS_mode != "requests" || FLAGS_pte.empty() ||
41+
FLAGS_tokenizer.empty() || FLAGS_max_sessions <= 0 ||
42+
FLAGS_max_session_tokens < 0) {
43+
throw std::invalid_argument(
44+
"invalid model or correctness workload flags");
45+
}
46+
const ci::RequestOptions options{
47+
FLAGS_requests,
48+
FLAGS_prompt_tokens,
49+
FLAGS_max_new_tokens,
50+
FLAGS_stagger_ms,
51+
FLAGS_max_decode,
52+
FLAGS_timeout_s};
53+
// Reject impossible workloads before loading tokenizer or model weights.
54+
ci::validate_requests(
55+
options, FLAGS_max_sessions, FLAGS_max_session_tokens);
56+
tokenizers::HFTokenizer tokenizer;
57+
if (tokenizer.load(FLAGS_tokenizer) != tokenizers::Error::Ok) {
58+
throw std::runtime_error("could not load the tokenizer");
59+
}
60+
llm::MuseGlimmerBackendConfig config;
61+
config.backend = FLAGS_backend;
62+
config.model_path = FLAGS_pte;
63+
config.data_path = FLAGS_data_path;
64+
config.max_sessions = FLAGS_max_sessions;
65+
config.max_session_tokens = FLAGS_max_session_tokens;
66+
config.bos_id = FLAGS_bos_id;
67+
auto backend = llm::create_muse_glimmer_backend(config);
68+
if (!backend.ok()) {
69+
throw std::runtime_error(
70+
"could not create the executor: error " +
71+
std::to_string(static_cast<int>(backend.error())));
72+
}
73+
ci::EvidenceExecutor executor(*backend->executor);
74+
llm::serving::ServingRuntimeConfig serving;
75+
serving.max_sessions = options.requests;
76+
serving.max_requests = options.requests;
77+
serving.max_pending_operations = options.requests;
78+
serving.max_context_length = backend->preparation->max_context_length;
79+
auto result = ci::run_requests(
80+
options,
81+
executor,
82+
tokenizer,
83+
serving,
84+
[spec = backend->preparation](
85+
const llm::serving::PromptPreparationContext& context,
86+
llm::serving::PromptInput input) {
87+
return llm::prepare_muse_glimmer_input(
88+
context, std::move(input), spec);
89+
});
90+
const auto evidence = executor.evidence();
91+
ci::check_batching(evidence);
92+
std::cout << "Batching correctness passed: " << result.accepted
93+
<< " requests completed with exact token budgets; "
94+
<< evidence.multi_session_steps
95+
<< " successful multi-session executor steps\n";
96+
return 0;
97+
} catch (const std::exception& error) {
98+
std::cerr << "batching smoke failed: " << error.what() << '\n';
99+
return 1;
100+
}
101+
}

0 commit comments

Comments
 (0)