[INTERPRETER] Make int1 add/sub wrap around like the GPU - #10923
Conversation
Head branch was pushed to by a user without write access
8eee3e8 to
ee62978
Compare
Update: fixed the failing interpreter testThe first push failed the
Why it was failing. My first version of the fix gated the new behavior on the Triton dtype: The fix. Key the branch off the actual numpy data instead, which is the ground truth for what the op executes on: if lhs.data.dtype == np.bool_ and rhs.data.dtype == np.bool_:
output = (op(lhs.data.astype(np.int8), rhs.data.astype(np.int8)) & 1).astype(np.bool_)
return TensorHandle(output, tl_dtype)Computing in The test is marked |
`bool + bool` in the interpreter used numpy's logical/saturating bool arithmetic (`True + True == True`), and `bool - bool` raised a TypeError outright. The GPU backend treats int1 as a 1-bit integer that wraps around, so `True + True == 0`. Compute int1 binary ops in a wider integer domain and truncate back to one bit so the interpreter matches the GPU. Fixes triton-lang#10919
70892ab to
ae54685
Compare
The interpreter stores bf16 as a uint16 bit pattern, but binary_op, unary_op, fma and dot ran the numpy op directly on that storage, so bf16 arithmetic and comparisons computed on the bit pattern instead of the value, diverging from the GPU. Convert to float32 before the op (as the GPU does) and round back to bf16 after. Adds interpreter tests for bf16 binary_op, comparison, neg and fma. (int1, the other half of triton-lang#10919, was fixed separately in triton-lang#10923.)
Summary
Fixes #10919.
int1 + int1produced different results in the interpreter and on the GPU:int1is a 1-bit integer, soarith.addiwraps mod 2 andTrue + True == 0.binary_opran numpy bool arithmetic, which is logical/saturating (True + True == True == 1), so it disagreed with the GPU.As noted by @peterbell10 in the issue,
0is the intended result (int1 should wrap like any other integer type), so the interpreter is the side to change; the GPU path is unchanged.This also fixes a related interpreter crash:
int1 - int1previously raisedTypeError: numpy boolean subtract ... is not supported, since numpy rejects bool subtraction. It now wraps correctly (matching the GPU).Change
In
InterpreterBuilder.binary_op, when the operand type isint1, compute the op in a wider integer domain (int8) and truncate back to one bit (& 1). This matches the GPU's 1-bit wraparound. Ops whose int1 results are already in{0, 1}(mul, and, or, xor, min, max, comparisons) are unaffected.Test
test_int1_bin_op_wraparoundintest_core.pyrunsint1 +/- int1and asserts mod-2 wraparound. Marked@pytest.mark.interpreterso it runs on both the GPU and interpreter paths, pinning them together.