From 8f182390dfb4e23baa53ceeea1d80d440b8a96b1 Mon Sep 17 00:00:00 2001 From: Nenad Banfic Date: Tue, 28 Jul 2026 00:59:32 +0000 Subject: [PATCH 1/4] Fix TensorScatter CPU issue --- .../core/providers/cpu/llm/tensorscatter.cc | 2 +- .../cpu/llm/tensorscatter_op_test.cc | 25 +++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/onnxruntime/core/providers/cpu/llm/tensorscatter.cc b/onnxruntime/core/providers/cpu/llm/tensorscatter.cc index 9fde9208d7c71..a90c596ecf7ec 100644 --- a/onnxruntime/core/providers/cpu/llm/tensorscatter.cc +++ b/onnxruntime/core/providers/cpu/llm/tensorscatter.cc @@ -16,7 +16,7 @@ ONNX_CPU_OPERATOR_KERNEL( 24, KernelDefBuilder() .MayInplace(0, 0) - .TypeConstraint("T", DataTypeImpl::AllTensorTypes()), + .TypeConstraint("T", DataTypeImpl::AllFixedSizeTensorTypes()), TensorScatter); TensorScatter::TensorScatter(const OpKernelInfo& info) : OpKernel(info) { diff --git a/onnxruntime/test/providers/cpu/llm/tensorscatter_op_test.cc b/onnxruntime/test/providers/cpu/llm/tensorscatter_op_test.cc index ff5f354a4b7aa..832a2693e2e34 100644 --- a/onnxruntime/test/providers/cpu/llm/tensorscatter_op_test.cc +++ b/onnxruntime/test/providers/cpu/llm/tensorscatter_op_test.cc @@ -354,5 +354,30 @@ TEST(TensorScatterTest, Circular_NegativeWriteIndex) { {}, nullptr, &execution_providers); } +// The CPU kernel only supports fixed-size element types (matching the CUDA +// kernel's type constraint). Non-fixed-size element types such as string are +// intentionally excluded because the kernel operates on raw memory buffers. +// Loading a graph that binds a string tensor to TensorScatter must fail at +// kernel resolution rather than at Compute time. +TEST(TensorScatterTest, StringType_NotSupported) { + OpTester test("TensorScatter", 24); + test.AddAttribute("mode", "linear"); + + test.AddInput("past_cache", {1, 4, 1}, + {"alpha", "beta", "gamma", "delta"}); + test.AddInput("update", {1, 1, 1}, {"omega"}); + test.AddInput("write_indices", {1}, {2}); + test.AddOutput("present_cache", {1, 4, 1}, + {"alpha", "beta", "omega", "delta"}); + + std::vector> execution_providers; + execution_providers.push_back(DefaultCpuExecutionProvider()); + // The graph resolver rejects the node when no kernel matches the string + // element type. The exact message is provider-dependent, so match on the + // common substring surfaced by the kernel lookup. + test.Run(OpTester::ExpectResult::kExpectFailure, "", + {}, nullptr, &execution_providers); +} + } // namespace test } // namespace onnxruntime From da54237b76a193be22418261f88ecdb5b4d57eb7 Mon Sep 17 00:00:00 2001 From: Nenad Banfic Date: Tue, 28 Jul 2026 18:24:21 +0000 Subject: [PATCH 2/4] Fix docs --- docs/OperatorKernels.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/OperatorKernels.md b/docs/OperatorKernels.md index 5f2da22aabe65..7a01ba1abe6c9 100644 --- a/docs/OperatorKernels.md +++ b/docs/OperatorKernels.md @@ -507,7 +507,7 @@ The **OpSet Version** column uses the following notation: |||[7, 21]|**T** = tensor(float)| |Tanh|*in* input:**T**
*out* output:**T**|13+|**T** = tensor(double), tensor(float)| |||[6, 12]|**T** = tensor(double), tensor(float)| -|TensorScatter|*in* past_cache:**T**
*in* update:**T**
*in* write_indices:**tensor(int64)**
*out* present_cache:**T**|24+|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|TensorScatter|*in* past_cache:**T**
*in* update:**T**
*in* write_indices:**tensor(int64)**
*out* present_cache:**T**|24+|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |TfIdfVectorizer|*in* X:**T**
*out* Y:**T1**|9+|**T** = tensor(int32), tensor(int64), tensor(string)
**T1** = tensor(float)| |ThresholdedRelu|*in* X:**T**
*out* Y:**T**|22+|**T** = tensor(float)| |||[10, 21]|**T** = tensor(float)| From 6a3b180c2f4b832815fb96e0258575a673767eba Mon Sep 17 00:00:00 2001 From: Nenad Banfic Date: Tue, 28 Jul 2026 18:36:09 +0000 Subject: [PATCH 3/4] Fix docs and copilot comment --- onnxruntime/test/providers/cpu/llm/tensorscatter_op_test.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/onnxruntime/test/providers/cpu/llm/tensorscatter_op_test.cc b/onnxruntime/test/providers/cpu/llm/tensorscatter_op_test.cc index 832a2693e2e34..94a765ad80cf0 100644 --- a/onnxruntime/test/providers/cpu/llm/tensorscatter_op_test.cc +++ b/onnxruntime/test/providers/cpu/llm/tensorscatter_op_test.cc @@ -375,7 +375,7 @@ TEST(TensorScatterTest, StringType_NotSupported) { // The graph resolver rejects the node when no kernel matches the string // element type. The exact message is provider-dependent, so match on the // common substring surfaced by the kernel lookup. - test.Run(OpTester::ExpectResult::kExpectFailure, "", + test.Run(OpTester::ExpectResult::kExpectFailure, "Failed to find kernel for", {}, nullptr, &execution_providers); } From 5c5506656f4fa96d446c7e2a1343cbbe6946f8fe Mon Sep 17 00:00:00 2001 From: Nenad Banfic Date: Wed, 29 Jul 2026 17:14:40 +0000 Subject: [PATCH 4/4] Match op name in expected failure substring so both partitioner and kernel-lookup paths pass --- .../test/providers/cpu/llm/tensorscatter_op_test.cc | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/onnxruntime/test/providers/cpu/llm/tensorscatter_op_test.cc b/onnxruntime/test/providers/cpu/llm/tensorscatter_op_test.cc index 94a765ad80cf0..5b2af54d309da 100644 --- a/onnxruntime/test/providers/cpu/llm/tensorscatter_op_test.cc +++ b/onnxruntime/test/providers/cpu/llm/tensorscatter_op_test.cc @@ -373,9 +373,11 @@ TEST(TensorScatterTest, StringType_NotSupported) { std::vector> execution_providers; execution_providers.push_back(DefaultCpuExecutionProvider()); // The graph resolver rejects the node when no kernel matches the string - // element type. The exact message is provider-dependent, so match on the - // common substring surfaced by the kernel lookup. - test.Run(OpTester::ExpectResult::kExpectFailure, "Failed to find kernel for", + // element type. The exact wording differs between the graph-partitioner + // path ("Could not find an implementation for ...") and the later kernel + // lookup path ("Failed to find kernel for ..."), so match on the op name + // which is present in both. + test.Run(OpTester::ExpectResult::kExpectFailure, "TensorScatter", {}, nullptr, &execution_providers); }