Skip to content

Commit 6750358

Browse files
authored
Merge pull request #1064 from intel/sync_msft_26042026
Sync with Microsoft ONNX Runtime - 26042026
2 parents 2db52dd + 19efec4 commit 6750358

25 files changed

Lines changed: 963 additions & 106 deletions

js/web/lib/wasm/jsep/webgpu/ops/attention.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -809,14 +809,17 @@ export const applyAttention = (
809809
) => {
810810
// Assumption is that presentKey/presentValue exists only if pastKey/pastValue exists.
811811
const outputCount = Math.min(context.outputCount, 1 + (pastKey ? 1 : 0) + (pastValue ? 1 : 0));
812+
// When there are no present key/value outputs (outputCount <= 1), ignore past to match CPU EP semantics.
813+
const effectivePastKey = outputCount > 1 ? pastKey : undefined;
814+
const effectivePastValue = outputCount > 1 ? pastValue : undefined;
812815
const pastSequenceLength = outputCount > 1 ? parameters.pastSequenceLength : 0;
813816
const totalSequenceLength = pastSequenceLength + parameters.kvSequenceLength;
814817
const attentionBias =
815818
attentionBiasInput && ShapeUtil.size(attentionBiasInput.dims) > 0 ? attentionBiasInput : undefined;
816819

817820
const inputsK = [q, k];
818-
if (outputCount > 1 && pastKey && ShapeUtil.size(pastKey.dims) > 0) {
819-
inputsK.push(pastKey);
821+
if (effectivePastKey && ShapeUtil.size(effectivePastKey.dims) > 0) {
822+
inputsK.push(effectivePastKey);
820823
}
821824
if (attentionBias) {
822825
inputsK.push(attentionBias);
@@ -833,7 +836,7 @@ export const applyAttention = (
833836
outputCount,
834837
q,
835838
k,
836-
pastKey,
839+
effectivePastKey,
837840
attentionBias,
838841
parameters,
839842
pastSequenceLength,
@@ -860,8 +863,8 @@ export const applyAttention = (
860863

861864
// Run AttentionScore
862865
const inputsV = [probs, v];
863-
if (outputCount > 1 && pastValue && ShapeUtil.size(pastValue.dims) > 0) {
864-
inputsV.push(pastValue);
866+
if (effectivePastValue && ShapeUtil.size(effectivePastValue.dims) > 0) {
867+
inputsV.push(effectivePastValue);
865868
}
866869
if (seqLens) {
867870
inputsV.push(seqLens);
@@ -874,7 +877,7 @@ export const applyAttention = (
874877
outputCount,
875878
probs,
876879
v,
877-
pastValue,
880+
effectivePastValue,
878881
parameters,
879882
pastSequenceLength,
880883
seqLens,

onnxruntime/contrib_ops/cpu/attnlstm/uni_dir_attn_lstm.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ void UniDirectionalAttnLstm<T>::LoadPeepholeWeights(const gsl::span<const T>& pe
216216
template <typename T>
217217
void UniDirectionalAttnLstm<T>::LoadBias(const gsl::span<const T>& WbRb_values) {
218218
const size_t hidden_size = CheckedToSizeT(hidden_size_);
219-
const size_t Wb_to_Rb_offset = CheckedMulToSizeT(hidden_size_, 4);
219+
const size_t Wb_to_Rb_offset = CheckedMulToSizeT(hidden_size, size_t{4});
220220

221221
// add Wb and Rb
222222
auto copy_fused_bias = [&WbRb_values, hidden_size, Wb_to_Rb_offset](size_t offset, gsl::span<T>& out) {

onnxruntime/contrib_ops/cpu/bert/rotary_embedding.cc

Lines changed: 60 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,19 @@
33

44
#include "contrib_ops/cpu/bert/rotary_embedding.h"
55
#include "contrib_ops/cpu/bert/rotary_embedding_helper.h"
6+
#include "core/providers/cpu/llm/rotary_embedding_int32_utils.h"
7+
8+
#include <algorithm>
9+
#include <limits>
610

711
#include "core/mlas/inc/mlas.h"
812
#include "core/platform/threadpool.h"
913

1014
using onnxruntime::concurrency::ThreadPool;
1115
using namespace onnxruntime::contrib::rotary_embedding_helper;
16+
using onnxruntime::rotary_embedding_int32_utils::CheckedAddToPtrdiff;
17+
18+
using onnxruntime::rotary_embedding_int32_utils::CheckedPtrdiffMulToPtrdiff;
1219

1320
namespace onnxruntime {
1421
namespace contrib {
@@ -32,8 +39,16 @@ REGISTER_KERNEL_TYPED(MLFloat16)
3239
template <typename T>
3340
RotaryEmbedding<T>::RotaryEmbedding(const OpKernelInfo& info) : OpKernel(info) {
3441
scale = info.GetAttrOrDefault<float>("scale", 1.0);
35-
rotary_embedding_dim = static_cast<int>(info.GetAttrOrDefault<int64_t>("rotary_embedding_dim", 0));
36-
num_heads = static_cast<int>(info.GetAttrOrDefault<int64_t>("num_heads", 0));
42+
const int64_t rotary_embedding_dim_attr = info.GetAttrOrDefault<int64_t>("rotary_embedding_dim", 0);
43+
const int64_t num_heads_attr = info.GetAttrOrDefault<int64_t>("num_heads", 0);
44+
ORT_ENFORCE(rotary_embedding_dim_attr >= 0 && rotary_embedding_dim_attr <= std::numeric_limits<int>::max(),
45+
"rotary_embedding_dim must be in range [0, ", std::numeric_limits<int>::max(),
46+
"]. Actual value: ", rotary_embedding_dim_attr);
47+
ORT_ENFORCE(num_heads_attr >= 0 && num_heads_attr <= std::numeric_limits<int>::max(),
48+
"num_heads must be in range [0, ", std::numeric_limits<int>::max(),
49+
"]. Actual value: ", num_heads_attr);
50+
rotary_embedding_dim = static_cast<int>(rotary_embedding_dim_attr);
51+
num_heads = static_cast<int>(num_heads_attr);
3752
interleaved = (info.GetAttrOrDefault<int64_t>("interleaved", 0) == 1);
3853
is_packed_batching = (info.GetAttrOrDefault<int64_t>("is_packed_batching", 0) == 1);
3954

@@ -72,8 +87,12 @@ Status RunRotaryEmbedding(concurrency::ThreadPool* tp, RotaryParameters paramete
7287
" exceeds cos/sin cache range [0, ", max_sequence_length, ")");
7388
}
7489
} else if (position_ids_format == 1) {
90+
std::ptrdiff_t position_count = 0;
91+
ORT_RETURN_IF_ERROR(onnxruntime::rotary_embedding_int32_utils::CheckedMulToPtrdiff(
92+
batch_size, sequence_length, "position_ids element count", position_count));
93+
7594
// Format 1: 2D array (batch_size, sequence_length)
76-
for (int i = 0; i < batch_size * sequence_length; ++i) {
95+
for (std::ptrdiff_t i = 0; i < position_count; ++i) {
7796
int64_t pos = position_ids[i];
7897
if (pos < 0 || pos >= static_cast<int64_t>(max_sequence_length)) {
7998
return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT,
@@ -84,7 +103,37 @@ Status RunRotaryEmbedding(concurrency::ThreadPool* tp, RotaryParameters paramete
84103
}
85104

86105
// Parallel to calculate based on head_size
87-
const int loop_len = batch_size * sequence_length * n_heads;
106+
std::ptrdiff_t loop_len = 0;
107+
ORT_RETURN_IF_ERROR(onnxruntime::rotary_embedding_int32_utils::CheckedMulToPtrdiff(
108+
batch_size, sequence_length, n_heads, "total_elements", loop_len));
109+
110+
std::ptrdiff_t max_batch_offset = 0;
111+
std::ptrdiff_t max_seq_offset = 0;
112+
std::ptrdiff_t max_head_offset = 0;
113+
std::ptrdiff_t max_block_offset = 0;
114+
std::ptrdiff_t max_b_s_index = 0;
115+
[[maybe_unused]] std::ptrdiff_t max_cache_offset = 0;
116+
ORT_RETURN_IF_ERROR(onnxruntime::rotary_embedding_int32_utils::CheckedMulToPtrdiff(
117+
std::max(batch_size - 1, 0), batch_stride, "max_batch_offset", max_batch_offset));
118+
ORT_RETURN_IF_ERROR(onnxruntime::rotary_embedding_int32_utils::CheckedMulToPtrdiff(
119+
std::max(sequence_length - 1, 0), seq_stride, "max_seq_offset", max_seq_offset));
120+
ORT_RETURN_IF_ERROR(onnxruntime::rotary_embedding_int32_utils::CheckedMulToPtrdiff(
121+
std::max(n_heads - 1, 0), head_stride, "max_head_offset", max_head_offset));
122+
ORT_RETURN_IF_ERROR(onnxruntime::rotary_embedding_int32_utils::CheckedAddToPtrdiff(
123+
max_batch_offset, max_seq_offset, "max_block_offset", max_block_offset));
124+
ORT_RETURN_IF_ERROR(onnxruntime::rotary_embedding_int32_utils::CheckedAddToPtrdiff(
125+
max_block_offset, max_head_offset, "max_block_offset", max_block_offset));
126+
if (position_ids_format == 0) {
127+
std::ptrdiff_t total_b_s_count = 0;
128+
ORT_RETURN_IF_ERROR(onnxruntime::rotary_embedding_int32_utils::CheckedMulToPtrdiff(
129+
batch_size, sequence_length, "total_b_s_count", total_b_s_count));
130+
max_b_s_index = total_b_s_count > 0 ? total_b_s_count - 1 : 0;
131+
} else {
132+
max_b_s_index = std::max(max_sequence_length - 1, 0);
133+
}
134+
ORT_RETURN_IF_ERROR(onnxruntime::rotary_embedding_int32_utils::CheckedPtrdiffMulToPtrdiff(
135+
max_b_s_index, half_rotary_emb_dim, "max_cache_offset", max_cache_offset));
136+
88137
// The cost is calculated as:
89138
// - head_size * sizeof(T) for reading input
90139
// - head_size * sizeof(T) for writing output
@@ -97,16 +146,18 @@ Status RunRotaryEmbedding(concurrency::ThreadPool* tp, RotaryParameters paramete
97146
const int n = static_cast<int>(ptr % n_heads);
98147
// Identify the index of batch, sequence, and head (specific range) in the input/output tensor
99148
// for read/write
100-
const int block_offset = b * batch_stride + s * seq_stride + n * head_stride;
149+
const std::ptrdiff_t block_offset = static_cast<std::ptrdiff_t>(b) * batch_stride +
150+
static_cast<std::ptrdiff_t>(s) * seq_stride +
151+
static_cast<std::ptrdiff_t>(n) * head_stride;
101152

102153
const T* input_data = input + block_offset;
103154
T* output_data = output + block_offset;
104155

105156
// Cache is (M, H/2) or (M, rotary_embedding_dim/2)
106-
const int position_id = (position_ids_format == 0)
107-
? static_cast<int>(position_ids[0]) + s
108-
: static_cast<int>(position_ids[b * sequence_length + s]);
109-
const int cache_offset = position_id * half_rotary_emb_dim;
157+
const std::ptrdiff_t position_id = (position_ids_format == 0)
158+
? static_cast<std::ptrdiff_t>(position_ids[0]) + s
159+
: static_cast<std::ptrdiff_t>(position_ids[static_cast<std::ptrdiff_t>(b) * sequence_length + s]);
160+
const std::ptrdiff_t cache_offset = position_id * half_rotary_emb_dim;
110161
const T* cos_data = cos_cache + cache_offset;
111162
const T* sin_data = sin_cache + cache_offset;
112163

onnxruntime/contrib_ops/cpu/bert/rotary_embedding_helper.h

Lines changed: 78 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,20 @@
22
// Licensed under the MIT License.
33

44
#pragma once
5+
56
#include "core/common/common.h"
67
#include "core/providers/common.h"
8+
#include "core/providers/cpu/llm/rotary_embedding_int32_utils.h"
79

810
namespace onnxruntime {
911
namespace contrib {
1012
namespace rotary_embedding_helper {
1113

14+
namespace detail {
15+
using onnxruntime::rotary_embedding_int32_utils::CheckedMulToInt32;
16+
using onnxruntime::rotary_embedding_int32_utils::NarrowNonNegativeToInt32;
17+
} // namespace detail
18+
1219
// Parameters deduced from node attributes and inputs/outputs.
1320
struct RotaryParameters {
1421
int batch_size; // Batch size used by input
@@ -73,20 +80,52 @@ Status CheckInputs(const T* input,
7380
}
7481

7582
// Get attributes from inputs
76-
int batch_size = static_cast<int>(input_dims[0]);
77-
int sequence_length = static_cast<int>(input_dims[1]);
78-
int hidden_size = static_cast<int>(input_dims[2]);
83+
int batch_size = 0;
84+
int sequence_length = 0;
85+
int hidden_size = 0;
86+
int head_size = 0;
87+
88+
ORT_RETURN_IF_ERROR(detail::NarrowNonNegativeToInt32(input_dims[0], "batch_size", batch_size));
89+
ORT_RETURN_IF_ERROR(detail::NarrowNonNegativeToInt32(input_dims[1], "sequence_length", sequence_length));
90+
ORT_RETURN_IF_ERROR(detail::NarrowNonNegativeToInt32(input_dims[2], "hidden_size", hidden_size));
7991

8092
bool transposed = false;
8193
if (input_dims.size() == 4) {
8294
// input is [batch, num_heads, seq, head_size]
83-
sequence_length = static_cast<int>(input_dims[2]);
84-
hidden_size = static_cast<int>(input_dims[1]) * static_cast<int>(input_dims[3]);
95+
ORT_RETURN_IF_ERROR(detail::NarrowNonNegativeToInt32(input_dims[2], "sequence_length", sequence_length));
96+
ORT_RETURN_IF_ERROR(detail::NarrowNonNegativeToInt32(input_dims[1], "num_heads", num_heads));
97+
ORT_RETURN_IF_ERROR(detail::NarrowNonNegativeToInt32(input_dims[3], "head_size", head_size));
98+
ORT_RETURN_IF_ERROR(detail::CheckedMulToInt32(num_heads, head_size, "hidden_size", hidden_size));
8599
transposed = true;
100+
} else if (num_heads > 0) {
101+
if (hidden_size % num_heads != 0) {
102+
return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT,
103+
"RotaryEmbedding: hidden_size=", hidden_size,
104+
" must be divisible by num_heads=", num_heads,
105+
" for rank-3 input");
106+
}
107+
head_size = static_cast<int>(hidden_size / num_heads);
108+
if (batch_size > 0 && sequence_length > 0 && hidden_size > 0 && head_size <= 0) {
109+
return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT,
110+
"RotaryEmbedding: head_size must be greater than 0 for non-empty rank-3 input");
111+
}
112+
}
113+
int max_sequence_length = 0;
114+
ORT_RETURN_IF_ERROR(detail::NarrowNonNegativeToInt32(cos_cache_dims[0], "max_sequence_length", max_sequence_length));
115+
if (rotary_embedding_dim == 0) {
116+
int cache_width = 0;
117+
ORT_RETURN_IF_ERROR(detail::NarrowNonNegativeToInt32(cos_cache_dims[1], "cache_width", cache_width));
118+
if (head_size == 0) {
119+
ORT_RETURN_IF_ERROR(detail::CheckedMulToInt32(cache_width, 2, "head_size", head_size));
120+
}
121+
} else {
122+
if (!transposed) {
123+
if (num_heads <= 0) {
124+
return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT,
125+
"RotaryEmbedding: num_heads must be greater than 0 for rank-3 input");
126+
}
127+
}
86128
}
87-
int max_sequence_length = static_cast<int>(cos_cache_dims[0]);
88-
int head_size = rotary_embedding_dim == 0 ? static_cast<int>(cos_cache_dims[1]) * 2
89-
: static_cast<int>(hidden_size / num_heads);
90129
if (rotary_embedding_dim > 0 && rotary_embedding_dim > head_size) {
91130
return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, "rotary_embedding_dim must be less than or equal to ",
92131
"head_size");
@@ -96,11 +135,16 @@ Status CheckInputs(const T* input,
96135

97136
// Check position_ids input shapes
98137
if (!onnxruntime::IsScalarOr1ElementVector(position_ids)) {
99-
if (batch_size != static_cast<int>(position_ids_dims[0])) {
138+
int position_ids_batch = 0;
139+
int position_ids_sequence = 0;
140+
ORT_RETURN_IF_ERROR(detail::NarrowNonNegativeToInt32(position_ids_dims[0], "position_ids_dim0", position_ids_batch));
141+
ORT_RETURN_IF_ERROR(detail::NarrowNonNegativeToInt32(position_ids_dims[1], "position_ids_dim1", position_ids_sequence));
142+
143+
if (batch_size != position_ids_batch) {
100144
return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, "Input 'position_ids' dimension 0 should be of size ",
101145
"batch_size, got ", position_ids_dims[0]);
102146
}
103-
if (sequence_length != static_cast<int>(position_ids_dims[1])) {
147+
if (sequence_length != position_ids_sequence) {
104148
return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, "Input 'position_ids' dimension 1 should be of size ",
105149
"sequence_length, got ", position_ids_dims[1]);
106150
}
@@ -114,26 +158,44 @@ Status CheckInputs(const T* input,
114158
return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, "Input 'cos_cache' dimension 0 should be same as ",
115159
"max_sequence_length, got ", cos_cache_dims[0]);
116160
}
117-
if ((head_size / 2) != static_cast<int>(cos_cache_dims[1]) && (rotary_embedding_dim > 0 && (rotary_embedding_dim / 2) != static_cast<int>(cos_cache_dims[1]))) {
161+
if ((head_size / 2) != static_cast<int>(cos_cache_dims[1]) &&
162+
(rotary_embedding_dim <= 0 || (rotary_embedding_dim / 2) != static_cast<int>(cos_cache_dims[1]))) {
118163
return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT, "Input 'cos_cache' dimension 1 should be same as ",
119164
"head_size / 2 or rotary_embedding_dim / 2, got ", cos_cache_dims[1]);
120165
}
121166

122-
num_heads = num_heads > 0 ? num_heads : static_cast<int>(hidden_size / head_size);
167+
if (num_heads <= 0) {
168+
if (head_size == 0) {
169+
if (batch_size == 0 || sequence_length == 0 || hidden_size == 0) {
170+
num_heads = 0;
171+
} else {
172+
return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT,
173+
"RotaryEmbedding: head_size must be greater than 0 when inferring num_heads");
174+
}
175+
} else {
176+
if (hidden_size % head_size != 0) {
177+
return ORT_MAKE_STATUS(ONNXRUNTIME, INVALID_ARGUMENT,
178+
"RotaryEmbedding: hidden_size=", hidden_size,
179+
" must be divisible by inferred head_size=", head_size,
180+
" when inferring num_heads");
181+
}
182+
num_heads = static_cast<int>(hidden_size / head_size);
183+
}
184+
}
123185
// Calculate stride values
124186
int head_stride;
125187
int seq_stride;
126188
int batch_stride;
127189
if (transposed) {
128190
// Transposed input tensor shape is [batch, n_heads, seq_len, head_size]
129191
seq_stride = head_size;
130-
head_stride = sequence_length * seq_stride;
131-
batch_stride = num_heads * head_stride;
192+
ORT_RETURN_IF_ERROR(detail::CheckedMulToInt32(sequence_length, seq_stride, "head_stride", head_stride));
193+
ORT_RETURN_IF_ERROR(detail::CheckedMulToInt32(num_heads, head_stride, "batch_stride", batch_stride));
132194
} else {
133195
// Default input tensor shape is [batch, seq_len, hidden_size]
134196
head_stride = head_size;
135-
seq_stride = num_heads * head_stride;
136-
batch_stride = sequence_length * seq_stride;
197+
ORT_RETURN_IF_ERROR(detail::CheckedMulToInt32(num_heads, head_stride, "seq_stride", seq_stride));
198+
ORT_RETURN_IF_ERROR(detail::CheckedMulToInt32(sequence_length, seq_stride, "batch_stride", batch_stride));
137199
}
138200

139201
// Set rotary parameters

0 commit comments

Comments
 (0)