WASM backend: cast to bool, conv2d/maxPool3d with pad "same", and oneHot with float values disagree with the CPU backend

Abierto
#8,759 0 comentarios 0 reacciones 0 asignados Ver en GitHub

Nadie ha tomado este issue todavía.

Evaluación

Dificultad
4/5
Tiempo estimado
3-5 días
Aptitud para principiantes
28/100
Tipo de issue
Error
Claridad
Bastante claro
Estado de actividad
Activo
Stack tecnológico
cpp, javascript, typescript, wasm

Línea de trabajo

Four separate wasm kernels are involved: kernels/Cast.ts for the bool cast, the conv2d and depthwiseConv2d SAME-padding path that goes through XNNPACK, MaxPool3D.cc and MaxPoolWithArgmax.cc for the initial max value, and OneHot.cc for the on/off value types. Run the repro snippets with node repro.js cpu and node repro.js wasm to confirm each mismatch. Done means every wasm output matches the cpu backend for those cases.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

Four wasm-backend kernels give different results from the cpu backend.

System information

  • Custom code: yes
  • OS: Linux x86_64 (Debian 12)
  • TensorFlow.js installed from: npm
  • Version: @tensorflow/tfjs 4.22.0, @tensorflow/tfjs-backend-wasm 4.22.0, Node 20.20.2

All snippets use this header and run as node repro.js cpu and node repro.js wasm:

const tf = require('@tensorflow/tfjs')
require('@tensorflow/tfjs-backend-wasm')
const show = (t) => console.log(Array.from(t.dataSync()))
;(async () => { await tf.setBackend(process.argv[2]); await tf.ready()
  // case code here
})()

1. cast to bool truncates instead of testing for non-zero

show(tf.cast(tf.tensor1d([0.5, 2, 256, Infinity, NaN, 0]), 'bool'))
show(tf.cast(tf.tensor1d([1, 2, 256, 0], 'int32'), 'bool'))

wasm: [0, 2, 0, 0, 0, 0] and [1, 2, 0, 0]
cpu: [1, 1, 1, 1, 1, 0] and [1, 1, 1, 0]

kernels/Cast.ts does outVals.set(inVals) into a Uint8Array.

2. conv2d / depthwiseConv2d with pad 'same' return zeros when the filter is smaller than the stride

const x = tf.tensor4d([1, 2, 3, 4, 5, 6, 7, 8], [1, 2, 4, 1])
const f = tf.tensor4d([1, 1, 1], [1, 3, 1, 1])
show(tf.conv2d(x, f, 2, 'same'))
show(tf.depthwiseConv2d(x, f, 2, 'same'))

wasm: [0, 0] and [0, 0]
cpu: [6, 7] and [6, 7]

The total SAME padding here is -1. The pinned XNNPACK computes it as an unsigned size_t without clamping at 0.

3. maxPool3d / maxPoolWithArgmax return 1.17e-38 when the whole window is negative

show(tf.maxPool3d(tf.tensor5d([-1, -2, -3, -4], [1, 1, 2, 2, 1]), [1, 2, 2], 1, 'valid'))
show(tf.maxPoolWithArgmax(tf.tensor4d([-1, -2, -3, -4], [1, 2, 2, 1]), 2, 1, 'valid').result)

wasm: [1.1754943508222875e-38] and [1.1754943508222875e-38]
cpu: [-1] and [-1]

MaxPool3D.cc and MaxPoolWithArgmax.cc start from std::numeric_limits<float>::min() instead of lowest().

4. oneHot with float32 output ignores fractional on/off values

show(tf.oneHot(tf.tensor1d([0, 2], 'int32'), 3, 0.5, 0.25, 'float32'))
show(tf.oneHot(tf.tensor1d([0, 2], 'int32'), 3, 1, -1, 'float32'))

wasm: [0, 0, 0, 0, 0, 0] and [1.401298464324817e-45, NaN, NaN, NaN, NaN, 1.401298464324817e-45]
cpu: [0.5, 0.25, 0.25, 0.25, 0.25, 0.5] and [1, -1, -1, -1, -1, 1]

OneHot.cc takes int32_t on/off values and always writes through i32_write().

Found with a differential-testing tool; the report was drafted with AI assistance and reviewed and edited by me.

Credit: https://ucsbplse.github.io/

Lenguaje dominante
TypeScript
Estrellas
19.2k
Forks
2k
Métricas de merge de PR
Sin PR fusionados en 30 d

Preparar el entorno

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de tensorflow/tfjs

Todos los issues de tensorflow/tfjs

Issues similares

Más issues de TypeScript

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.