Add CPU Cast op support for Float8E8M0

Merged
TI
6mo ago
+510-40

Description

This PR adds Float8E8M0 support to the CPU Cast operator, implementing follow-up items 3 (Cast op support) and 4 (rounding mode) from PR #28381.

Changes

Float8E8M0 RoundMode (include/onnxruntime/core/common/float8.h)

  • Added RoundMode enum (Up, Down, Nearest) to Float8E8M0 struct
  • Extended the constructor with an optional round_mode parameter (default: Up)
  • Up/Nearest: ties round away from zero (higher power of 2)
  • Down: ties round towards zero (lower power of 2)
  • Backward-compatible — existing callers use the default Up mode

CPU Cast op (onnxruntime/core/providers/cpu/tensor/cast_op.cc)

  • Added Float8E8M0 to the Cast kernel's enabled type list (AllIRv10WithInt2)
  • Added FLOAT8E8M0 to the saturate attribute validation
  • Added round_mode attribute parsing ("up", "down", "nearest") per the ONNX opset 25 Cast schema
  • Added CastToE8M0Dispatcher template that handles casting from any source type (float, double, int, MLFloat16, BFloat16, Int4, Int2, string, other Float8 types) to Float8E8M0 with proper saturate and round_mode support
  • E8M0 destination dispatch is handled separately from the other Float8 types to thread round_mode through

Tests (onnxruntime/test/providers/cpu/tensor/cast_op_test.cc)

  • 10 new tests:
    • FloatToFloat8E8M0_Saturate / _NoSaturate — basic float→E8M0 with saturate on/off
    • FloatToFloat8E8M0_RoundModeUp / _RoundModeDown / _RoundModeNearest — all three rounding modes
    • Float8E8M0ToFloat / Float8E8M0ToDouble — E8M0→float/double conversion
    • MLFloat16ToFloat8E8M0 / DoubleToFloat8E8M0 / Int32ToFloat8E8M0 — various source types

Motivation and Context

PR #28381 added the Float8E8M0 data type to ORT but deferred Cast op support. This PR completes the Cast op integration so that models can use Cast(to=FLOAT8E8M0) with proper saturate and round_mode semantics as defined in the ONNX opset 25 spec.

Testing

All 10 new Cast op tests pass. All 19 existing Float8E8M0 unit tests and all 4 existing Float8 Cast tests continue to pass.

./onnxruntime_provider_test --gtest_filter="CastOpTest.*Float8E8M0*"
./onnxruntime_test_all --gtest_filter="Float8E8M0_Tests.*"
./onnxruntime_provider_test --gtest_filter="CastOpTest.ToFloat8*"