ID: PyTorch PR-1
This patch resolves a critical numerical divergence inside the PyTorch core library regarding how torch.sign handles NaN (Not a Number) floating-point elements. By replacing relational comparison dependencies with an explicit NaN-interception architecture, this modification ensures strict adherence to modern IEEE 754 floating-point standards and unifies execution parity across both CPU (SIMD Vectorized) and GPU (CUDA Threaded) runtimes.
Engineering Deconstruction
1. The Architectural Flaw (The Root Cause)
Previously, both the CPU and CUDA hardware backend kernels computed the numerical sign of a tensor element using raw relational comparison arithmetic expressions equivalent to:
$$\text{Result} = (0 < a) - (a < 0)$$
According to the IEEE 754 specification, any relational comparison operations evaluated directly against a NaN element must return false. Because of this constraint, when a NaN entered the execution block:
- $0 < \text{NaN} \implies \text{false} \ (0)$
- $\text{NaN} < 0 \implies \text{false} \ (0)$
- $\text{Result} = 0 - 0 = 0$
This configuration silently swallowed the arithmetic NaN state, transforming an undefined input value into a normal, valid 0 tracking tensor, which broke expected downstream behavior in mathematical gradients and loss validation.
2. The Multi-Backend System Fix
To fix this without degrading processing speeds, the implementation handles the problem at the hardware compilation level for both devices:
-
Advanced CPU Kernel Path (
UnaryOpsKernel.cpp): -
Scalar Fallback: Integrated an immediate type-safe intercept layer using
at::_isnan(a). If true, the branch bypasses relational arithmetic entirely and returns the originalNaNelement. -
SIMD Vectorization: Packaged hardware registers to calculate masks using
self_vec.isnan(). It applies a precise bitwise rewrite step viaVectorized<scalar_t>::blendvto preserve original uncorrupted data lanes right before register return. -
Parallel GPU Kernel Path (
UnarySignKernels.cu): -
Upgraded the global device execution lambda (
[]GPU_LAMBDA) to intercept thread blocks viaat::_isnan(a)before the variable drops down into the low-levelc10::signum(a)macro block.
Comments 0
No comments yet. Be the first!
Sign in to join the conversation.