Skip to content

Commit 0b7f637

Browse files
committed
Update
[ghstack-poisoned]
2 parents 5d188d6 + a8580c6 commit 0b7f637

10 files changed

Lines changed: 59 additions & 298 deletions

File tree

backends/webgpu/runtime/WebGPUBackend.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,14 +106,13 @@ Error WebGPUBackend::execute(
106106
tensor.scalar_type() == executorch::aten::ScalarType::Long;
107107
inputs.push_back({tensor.const_data_ptr(), tensor.nbytes(), host_is_int64});
108108
}
109-
graph->copy_inputs(inputs);
110-
111109
// Fail loud as a runtime Error so a throw never crosses the backend boundary.
112110
try {
111+
graph->copy_inputs(inputs);
113112
graph->update_symints_from_inputs(inputs);
114113
graph->propagate_resize();
115114
} catch (const std::exception& e) {
116-
ET_LOG(Error, "WebGPU symint refresh/resize failed: %s", e.what());
115+
ET_LOG(Error, "WebGPU input copy / symint refresh failed: %s", e.what());
117116
return Error::Internal;
118117
}
119118

backends/webgpu/runtime/WebGPUGraph.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,10 @@ void WebGPUGraph::build(
319319
"WebGPU: constant_id set but the constants table is missing "
320320
"or the id is out of range");
321321
}
322+
} else if (constant_id >= 0 && tensor.nbytes > 0) {
323+
// constant_id set but constant_data null -> fail loud.
324+
throw std::runtime_error(
325+
"WebGPU: constant_id set but constant_data is null");
322326
}
323327
} else {
324328
// Shared buffer: track required size, defer allocation to pass 2

backends/webgpu/runtime/ops/embedding_q4gsw/embedding_q4gsw.wgsl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
2727
let indices_idx = block / params.blocks_per_row;
2828
let base_dim = (block % params.blocks_per_row) * 32u;
2929

30+
// token assumed in-range (mirrors Vulkan; no vocab clamp).
3031
let token = u32(t_indices[indices_idx]);
3132
let row_byte_base = token * params.bytes_per_row;
3233
let out_base = indices_idx * params.embed_dim + base_dim;

backends/webgpu/runtime/ops/embedding_q4gsw/embedding_q4gsw_wgsl.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
namespace executorch::backends::webgpu {
1414

1515
// @generated from embedding_q4gsw.wgsl - DO NOT EDIT.
16-
// wgsl-sha256: b86f112c08bd73bdcbfed41a27fb63465ec36d1a50d0cdf2612684e30fceeac9
16+
// wgsl-sha256: 1fec9ed315696a88bb7db6c16454fc80e08ff73b0e39720b54515fda4ee1ef7c
1717
inline constexpr const char* kEmbeddingQ4gswWGSL = R"(
1818
@group(0) @binding(0) var<storage, read_write> t_out: array<f32>;
1919
@group(0) @binding(1) var<storage, read> t_indices: array<i32>;
@@ -44,6 +44,7 @@ fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
4444
let indices_idx = block / params.blocks_per_row;
4545
let base_dim = (block % params.blocks_per_row) * 32u;
4646
47+
// token assumed in-range (mirrors Vulkan; no vocab clamp).
4748
let token = u32(t_indices[indices_idx]);
4849
let row_byte_base = token * params.bytes_per_row;
4950
let out_base = indices_idx * params.embed_dim + base_dim;

backends/webgpu/runtime/ops/rope/RotaryEmbedding.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ void add_rope_dispatch(
5757
uint32_t head_dim,
5858
uint32_t workgroup_count) {
5959
const uint32_t half_dim = head_dim / 2u;
60+
// out.dims == in.dims (asserted in impl), so this matches the caller's wgc.
6061
const uint32_t num_pairs = static_cast<uint32_t>(numel_of(out.dims) / 2u);
6162

6263
RotaryParams params = {};

backends/webgpu/scripts/test_webgpu_native_ci.sh

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,9 @@ UPDATE_CACHE_OK=1
5050
EMBEDDING_MODEL="/tmp/webgpu_embedding_q4gsw.pte"
5151
EMBEDDING_INDICES="/tmp/webgpu_embedding_q4gsw_indices.bin"
5252
EMBEDDING_GOLDEN="/tmp/webgpu_embedding_q4gsw_golden.bin"
53-
ROPE_MODEL="/tmp/webgpu_rope.pte"
54-
ROPE_XQ_GOLDEN="/tmp/webgpu_rope_xq_golden.bin"
55-
ROPE_XK_GOLDEN="/tmp/webgpu_rope_xk_golden.bin"
53+
EMBEDDING_LLAMA1B_MODEL="/tmp/webgpu_embedding_q4gsw_llama1b.pte"
54+
EMBEDDING_LLAMA1B_INDICES="/tmp/webgpu_embedding_q4gsw_llama1b_indices.bin"
55+
EMBEDDING_LLAMA1B_GOLDEN="/tmp/webgpu_embedding_q4gsw_llama1b_golden.bin"
5656

5757
$PYTHON_EXECUTABLE -c "
5858
from executorch.backends.webgpu.test.ops.add.test_add import export_add_model, export_chained_add_model
@@ -68,12 +68,8 @@ export_all_quantized_linear_models('/tmp')
6868
$PYTHON_EXECUTABLE -c "
6969
from executorch.backends.webgpu.test.ops.embedding_q4gsw.test_embedding_q4gsw import export_embedding_q4gsw_model
7070
export_embedding_q4gsw_model('${EMBEDDING_MODEL}', '${EMBEDDING_GOLDEN}', '${EMBEDDING_INDICES}')
71-
" || echo "WARN: embedding_q4gsw export failed; webgpu_native_test embedding case self-skips"
72-
73-
$PYTHON_EXECUTABLE -c "
74-
from executorch.backends.webgpu.test.ops.rope.test_rope import export_rope_model
75-
export_rope_model('${ROPE_MODEL}', '${ROPE_XQ_GOLDEN}', '${ROPE_XK_GOLDEN}')
76-
" || echo "WARN: rope export failed; webgpu_native_test apply_rotary_emb case self-skips"
71+
export_embedding_q4gsw_model('${EMBEDDING_LLAMA1B_MODEL}', '${EMBEDDING_LLAMA1B_GOLDEN}', '${EMBEDDING_LLAMA1B_INDICES}', 'llama1b')
72+
" || echo "WARN: embedding_q4gsw export failed; webgpu_native_test embedding cases self-skip"
7773

7874
$PYTHON_EXECUTABLE -c "
7975
from executorch.backends.webgpu.test.ops.rms_norm.test_rms_norm import export_rms_norm_cases
@@ -168,9 +164,9 @@ if [[ -x "${BIN_DIR}/webgpu_native_test" && -f "${PTE_MODEL}" ]]; then
168164
WEBGPU_TEST_EMBEDDING_Q4GSW_MODEL="${EMBEDDING_MODEL}" \
169165
WEBGPU_TEST_EMBEDDING_Q4GSW_INDICES="${EMBEDDING_INDICES}" \
170166
WEBGPU_TEST_EMBEDDING_Q4GSW_GOLDEN="${EMBEDDING_GOLDEN}" \
171-
WEBGPU_TEST_ROPE_MODEL="${ROPE_MODEL}" \
172-
WEBGPU_TEST_ROPE_XQ_GOLDEN="${ROPE_XQ_GOLDEN}" \
173-
WEBGPU_TEST_ROPE_XK_GOLDEN="${ROPE_XK_GOLDEN}" \
167+
WEBGPU_TEST_EMBEDDING_Q4GSW_LLAMA1B_MODEL="${EMBEDDING_LLAMA1B_MODEL}" \
168+
WEBGPU_TEST_EMBEDDING_Q4GSW_LLAMA1B_INDICES="${EMBEDDING_LLAMA1B_INDICES}" \
169+
WEBGPU_TEST_EMBEDDING_Q4GSW_LLAMA1B_GOLDEN="${EMBEDDING_LLAMA1B_GOLDEN}" \
174170
"${BIN_DIR}/webgpu_native_test"
175171
else
176172
echo "(skipping webgpu_native_test: no exported .pte — needs the executorch python wheel)"

backends/webgpu/test/ops/embedding_q4gsw/test_embedding_q4gsw.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,8 @@ def test_golden_matches_eager(self) -> None:
122122
weight, scales, group_size = _quant_params(qm)
123123
vocab = weight.shape[0]
124124
embed = weight.shape[1] * 2
125-
deq = torch.empty((vocab, embed), dtype=torch.float32)
125+
# fp64 reference dequant so the oracle carries no fp32 rounding.
126+
deq = torch.empty((vocab, embed), dtype=torch.float64)
126127
for row in range(vocab):
127128
for d in range(embed):
128129
byte = int(weight[row, d // 2])
@@ -131,7 +132,7 @@ def test_golden_matches_eager(self) -> None:
131132
deq[row, d] = (nib - 8) * scale
132133
eager = torch.nn.functional.embedding(idx, deq)
133134
golden = _golden(qm, idx)
134-
torch.testing.assert_close(golden, eager, atol=1e-5, rtol=1e-5)
135+
torch.testing.assert_close(golden.double(), eager, atol=1e-5, rtol=1e-5)
135136

136137

137138
def export_embedding_q4gsw_model(

backends/webgpu/test/ops/rope/__init__.py

Lines changed: 0 additions & 5 deletions
This file was deleted.

backends/webgpu/test/ops/rope/test_rope.py

Lines changed: 0 additions & 129 deletions
This file was deleted.

0 commit comments

Comments
 (0)