Summary
The spec’s reference algorithm for reduceLogSumExp overflows for inputs that the conformance tests expect to succeed. Additionally, the spec does not define any accuracy or numerical stability requirements for this operation, making it unclear what a conformant implementation must do.
The contradiction
The spec defines reduceLogSumExp with this reference decomposition:
function reduceLogSumExp(builder, input, options) {
return builder.log(builder.reduceSum(builder.exp(input), options));
}
However, the conformance tests include:
{
'name': 'reduceLogSumExp avoids overflows caused by taking the exp of large inputs',
'graph': {
'inputs': {
'reduceLogSumExpInput': {
'data': [100.0],
'descriptor': {shape: [1], dataType: 'float32'}
}
},
'operators': [{
'name': 'reduceLogSumExp',
'arguments': [
{'input': 'reduceLogSumExpInput'},
{'options': {'axes': [0], 'keepDimensions': false}}
],
'outputs': 'reduceLogSumExpOutput'
}],
'expectedOutputs': {
'reduceLogSumExpOutput': {
'data': [100.0],
'descriptor': {shape: [], dataType: 'float32'}
}
}
}
}
Tracing through the reference decomposition with this input:
exp(100.0) ≈ 2.69 × 10⁴³ → overflows float32 (max ≈ 3.40 × 10³⁸) → +inf
reduceSum([+inf]) → +inf
log(+inf) → +inf
Expected result: 100.0
Actual result from reference algorithm: +inf
The test name even acknowledges the issue (“avoids overflows caused by taking the exp of large inputs”), yet the normative algorithm does not avoid it.
Root cause
The log-sum-exp operation is numerically stable only when computed using the well-known max-subtraction trick:
reduceLogSumExp(x, axes) = max + log(sum(exp(x - max)))
where max = reduceMax(x, axes). This works because the outer log algebraically absorbs the exp(max) factor. Without the log wrapper (i.e., for plain reduceSum(exp(x))), no such trick is possible. The overflow is inherent to the result.
The entire purpose of reduceLogSumExp existing as a fused operation (rather than being decomposed by the user) is to enable this stable computation. The current spec text undermines that purpose.
Proposed fix
Replace the reference decomposition with the numerically stable formulation:
function reduceLogSumExp(builder, input, options) {
const max = builder.reduceMax(input, { ...options, keepDimensions: true });
const shifted = builder.sub(input, max);
const sumExp = builder.reduceSum(builder.exp(shifted), options);
const maxSqueezed = builder.reduceMax(input, options); // without keepDims
return builder.add(maxSqueezed, builder.log(sumExp));
}
Add normative text stating that implementations must compute reduceLogSumExp using a numerically stable algorithm, or at minimum specify accuracy bounds, e.g., the result must not overflow for any input where the mathematically exact result is representable in the output data type.
Additional concern: underspecified accuracy for reductions generally
The broader reduction operations section does not specify accuracy requirements for any reduction op. For reduceLogSumExp specifically, this means an implementation that naively follows the decomposition and returns +inf for exp(89) inputs is technically spec-conformant — but fails the conformance tests. The spec should be clear about what it expects.
Summary
The spec’s reference algorithm for reduceLogSumExp overflows for inputs that the conformance tests expect to succeed. Additionally, the spec does not define any accuracy or numerical stability requirements for this operation, making it unclear what a conformant implementation must do.
The contradiction
The spec defines reduceLogSumExp with this reference decomposition:
However, the conformance tests include:
Tracing through the reference decomposition with this input:
Expected result: 100.0
Actual result from reference algorithm: +inf
The test name even acknowledges the issue (“avoids overflows caused by taking the exp of large inputs”), yet the normative algorithm does not avoid it.
Root cause
The log-sum-exp operation is numerically stable only when computed using the well-known max-subtraction trick:
where
max = reduceMax(x, axes). This works because the outer log algebraically absorbs theexp(max)factor. Without the log wrapper (i.e., for plainreduceSum(exp(x))), no such trick is possible. The overflow is inherent to the result.The entire purpose of
reduceLogSumExpexisting as a fused operation (rather than being decomposed by the user) is to enable this stable computation. The current spec text undermines that purpose.Proposed fix
Replace the reference decomposition with the numerically stable formulation:
Add normative text stating that implementations must compute reduceLogSumExp using a numerically stable algorithm, or at minimum specify accuracy bounds, e.g., the result must not overflow for any input where the mathematically exact result is representable in the output data type.
Additional concern: underspecified accuracy for reductions generally
The broader reduction operations section does not specify accuracy requirements for any reduction op. For reduceLogSumExp specifically, this means an implementation that naively follows the decomposition and returns +inf for exp(89) inputs is technically spec-conformant — but fails the conformance tests. The spec should be clear about what it expects.