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

Aperta
#8,759 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
4/5
Tempo stimato
3-5 giorni
Idoneità per principianti
28/100
Tipo di issue
Bug
Chiarezza
Abbastanza chiara
Stato di attività
Attiva
Stack tecnologico
cpp, javascript, typescript, wasm

Direzione di ricerca

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.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

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/

Lingua principale
TypeScript
Stelle
19.2k
Fork
2k
Metriche di merge delle PR
Nessuna PR unita negli ultimi 30g

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di tensorflow/tfjs

Tutte le issue di tensorflow/tfjs

Issue simili

Altre issue su TypeScript

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.