You are browsing as a guest. Sign up (or log in) to start making projects!

3h 34m 28s logged

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 original NaN element.

  • SIMD Vectorization: Packaged hardware registers to calculate masks using self_vec.isnan(). It applies a precise bitwise rewrite step via Vectorized<scalar_t>::blendv to 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 via at::_isnan(a) before the variable drops down into the low-level c10::signum(a) macro block.

0
1

Comments 0

No comments yet. Be the first!